版本控制 (vcs) version control system
1. 版本控制是什么
记录一个或多个文件的变化, 以便将来查阅特定版本的内容
2. 为什么使用版本控制
记录, 怕丢失
多人协同开发
历史, 可以清楚的知道哪个时间点做了些什么
3. 发展
-
本地版本控制
- 基于文件差异
- 个人开发
- diff, patch
-
集中式版本控制 eg. svn
- 基于文件差异
- 远端库, 不存在本地库
- 多人开发
- 单点故障
-
分布式版本控制 eg. git
- 基于文件快照
- 本地库与远端库
- 多人并行开发 (完全并行), 环境隔离
- 安全, 可断网开发
4. git 与 svn 的区别
-
版本控制设计思路
svn 等集中式的版本控制管理, 都是基于文件差异来进行版本控制
- 每个版本均记录哪些文件有了更新, 以及更新了哪些行的哪些内容
git 是基于文件快照的版本控制
- 每个版本并不记录数据的差异, 而是比对文件的指纹信息并对文件做快照, 然后保存一个指向该快照的索引, 为了保证性能, 对于没有变化的文件, 不会再次保存新快照, 而是对原快照做一个链接
e.g: 记录人生成长的照片
由此可见, git 版本控制的设计有别于传统的版本控制思路
-
本地库与远端库 (local, origin)
svn 仅有集中式的远端库, 提交更新等几乎所有操作均需要网络
git 除了有远端库之外, 本地库也保留着和远端库一样的信息, 几乎所有操作均不需要网络即可操作, 比如查看修改历史
e.g: 意味着, 我们可以在坐飞机或者火车的时候, 也可以进行愉快的开发工作, 看起来区别不大, 实际体验过后, 你会惊喜的发现有很大的不同
-
工作区域的不同
svn 为 本地工作区域, 远端库
git 为 本地工作区域, 暂存区, 本地库, 远端库
e.g: 写多个纸张的作文 1. svn 方式: 统一把几张纸写完, 然后直接发给老师 2. git 方式: 写完一张, 放到一旁, 直到最终写完后, 统一发给老师 由此, git 引申出来文件的三个状态: 此处不再啰嗦了, committed, staged, modified
5. git 的强大之处 (分支)
- 分支的意义
几乎每一种版本控制系统都以某种形式支持分支功能, 使用分支意味着每个人的开发工作都与主线以及其他人分离隔离开来, 互不影响的进行工作
- 分支是 git 的 "必杀技"
很多版本控制系统中, 创建分支, 切换分支是一个昂贵的过程, 他们的实现方式往往是源目录的拷贝, 而 git 的创建分支以及分支切换几乎可以在瞬间完成, 无论项目大小均是如此, git 的出现, 改变了程序员的开发方式
-
分支的实现方式 (内容寻址)
-
上面说过, git 的版本控制对于每次提交都是以快照方式实现的, 而不是比较文件差异, 那么快照如何理解?
从图可以看到, 我们的每次提交都会生成一个SHA-1算法生成的字符串(姑且叫做索引), 所有的这类字符串可以理解为一个索引, 指向具体的数据对象, 可以看到提交对象中层层存储着更多的索引, 通过索引一步步的找到所对应的实际内容, tree 可以理解为目录
-
提交之间的上下级关系 (通过 parent)
-
分支的本质 (指向提交对象的可变指针)
分支其实就是从对应的提交对象追溯内容的过程
-
创建分支的过程, 其实就是在对应提交上新建一个指针指向该提交对象
-
git 会有一个当前所在指针 (名为 HEAD指针), 用来标识当前所在的分支
-
所以, 综上所述, 大家明白了为什么 git 的分支创建和切换的代价非常廉价了吧, 甚至可以一个项目同时进行几千个分支的开发都没有任何影响, 因为代价仅仅是创建指针(索引)而已, git 的分支创建以及切换和项目大小以及复杂度无关
-
-
分支的合并 (merge)
-
接到需求后, 基于 master 创建一个分支 iss53
-
完成了部分功能, iss53 进行了一次提交
-
此时, 功能还没开发完, 但是突然线上有问题需要解决, 此时基于 master 创建 hotfix 分支, 并修改 bug 进行提交
-
当 hotfix 分支测试完后, 要合并到 master 上线
-
回到未完成功能的分支 iss53 继续完成开发工作 (此分支完全不受任何影响)
-
此时 iss53 任务已完成, 需要合并 master 代码并上线
此 merge 操作会将 master 与 iss53 分支的末端 c4, c5 以及他们的共同祖先 c2 进行三方比较合并
-
合并上线之后
-
同 merge 类似的有个概念是 rebase 变基, 就先不在这里说了, 初学者对于变基的概念不清楚很容易出现问题, 后面有机会在说
-
6. 工作当中的一些经验
-
接到任务时, 第一时间要做的是切换到 master 分支, 创建一个新分支
git checkout master git fetch git pull git checkout -b liaoxing_xxx
-
代码开发到某阶段想要保存的时候
git add . // 当存在一些新建的未放入版本控制中的文件以及目录的时候使用 git commit -am "xxx" git push -u origin liaoxing_xxx // 推送到远端并跟踪
-
功能开发完毕后, 提测
// 先切换到 master 分支拉取最新代码 git checkout master git fetch git pull // 切换回开发分支, 合并 master 最新代码 git checkout liaoxing_xxx git merge master git commit -am "merge master" git push -u origin liaoxing_xxx // 切换到 develop 分支 git checkout develop git fetch git pull git merge liaoxing_xxx
-
测试完毕后, 上线
// 切换到 master, 获取最新代码 git checkout master git fetch git pull // 切换到开发分支, 合并 master 最新代码 git checkout liaoxing_xxx git merge master git commit -am "merge master" git push -u origin liaoxing_xxx // 切换到 master 分支, 合并代码 git checkout master git merge liaoxing_xxx
-
上面的命令看着很多, 只是为了保证百分之百不出错而已, 简单来说, 有如下经验
- 每次切换分支的时候, 都可以 git fetch, git pull 获取一下最新代码
- 经常要和 master 代码对齐