1.git 分支的合并(merge)
`假设我们此时需要修复dev分支上的某个bug,此时在dev分支上创建修复分支fix,然后推进fix分支.
当前的git仓库如图:
注:为了方便演示,dev分支上只有一个test.cpp源文件
`然后我们在fix分支上修复bug并做提交
在fix分支提交之后的git仓库如图:
此时bug已经修复完毕,我们把dev和fix分支进行合并:
合并之后,dev和fix分支指向同一位置
合并以后我们就可以删除修复分支fix
git branch -d fix
2.快进合并
fast-forward 是一种特殊的 merge :被合并的分支真包含请求合并的分支。
如上述情况的dev和fix分支,被合并的分支(fix)真包含请求合并的分支(dev);
`git 并不会创建一个新的合并提交对象 (merge-commit) 以表达两个分支的合并,而是直接把 dev 的指针前移,修改为与 fix 一致,这就是 fast forward 合并(快进合并)。
3.git:分支的三方合并
假设当前的git仓库如图:
我们在 add 分支添加一个源文件add.cpp,集结并做提交.
此时的git仓库如图:
假设此时我们想把add分支 和 dev分支进行合并:
`git会为合并分支自动识别出最佳的同源合并点,然后比较两个分支的差异,进行三方合并计算,然后进行合并.
通常三方合并git会用两个要合并的分支的末端提交节点和它们的共同祖先进行一次简单的三方合并计算.
上述情况的最佳的同源合并点就是 aee791
git会对dev,add分支的提交末端和aee791同源合并点三个节点进行合并计算,然后进行合并,同时创建一个包含合并结果的合并提交对象 (merge-commit).
上述情况比较简单,在add分支上添加了一个add.cpp源文件,dev分支上修改了test.cpp源文件,所以三方合并比较简单.合并成功后,新的合并提交节点就会同时添加add.cpp源文件和修改test.cpp源文件的内容.
如图:
4.冲突合并
如果三方合并计算时发生冲突,需要进行冲突合并.
注:这种情况虽然不同分支修改的是同一源文件,但是修改的源文件的内容,位置不同,(c2 修改的是return 1; c3 修改的是 #include <stdio.h>),git会自动合并成功.
4.1 自动合并失败情形 1
4.2 自动合并失败情形 2
如果合并出现冲突,就需要我们去手工去修改对应的冲突位置,然后再进行手工合并.
5.使用 rebase 进行合并
分支合并时,除了 merge 之外,还可使用另一种方式 rebase 。
rebase 可以使历史更清晰。如果查看一个 rebased 分支的日志,它看起来像一个线性历史 : 似乎所有的工作都是串行发生的,即使原来是并行发生的。
假设当前的git仓库如图:
在分支合并时,可以使用 C4 引入的变更补丁,在 C3上重新应用它。在 git 中,这称为 rebase 。使用 rebase 命令,可以获取在一个分支上提交的所有更改,然后在另一个分支上重演这些更改。
这个操作是这样进行的: 首先转到两个分支的共同祖先 ( 你所在的分支和你 rebasing onto 的分支 ) ,获得你所在分支每次提交时引入的差异,将这些差异保存到临时文件中,将当前分支重置为与你要 rebasing onto 的分支相同的提交,最后依次应用每个更改。
操作过程如图:
`合并成功:
`合并出现冲突(此情况为:要合并的两个分支末端提交节点对test.cpp同一位置进行了修改):
rebase 进行合并时出现冲突,test.cpp源文件的内容:
在 rebase 的过程中,也许会出现冲突 (conflict) 。
在这种情况, git 会停止 rebase 并会让你去解决冲突(修改冲突文件的内容);在解决完冲突后,用 “git-stage” 命令去更新这些内容的索引 (index)
然后,你无需执行 git-commit, 只要执行 : git rebase –continue 这样 git 会继续应用 (apply) 余下的补丁。
解决冲突以后的源文件:
解决冲突以后的合并过程: