合并分支操作在实际开放中很常用。

Fast-forward 向前合并

在 master 分支上新建了一个 hotfix 分支来修复一些问题,然后将这个修补补丁合并到 master 分支上。

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

像这种想要合并的分支 hotfix 所指向的提交 C4 是你所在的提交 C2 的直接后继, 因此 Git 会直接将指针向前移动。换句话说,当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。

当然合并完成后会遗留一个跟 master 重叠的指针 hotfix,将其删除即可:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

分叉合并

当目前所完成的分支是从 master 分支的更早版本分叉出来的时,将其合并到 master 分支会进行三方合并。

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

master 分支所在提交并不是 iss53 分支所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4C5)以及这两个分支的公共祖先(C2),做一个简单的三方合并。

和之前将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。

遇到冲突的分叉合并

C4C5 中都有关于从 C2 继承过来的文件的修改,且修改的内容不一样时,就出现了合并冲突。

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

执行完成后,Git 会把其余没有冲突的部分合并,然后等待你去解决合并产生的冲突(此时仍未创建新的合并提交)。

你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
 
Unmerged paths:
  (use "git add <file>..." to mark resolution)
 
    both modified:      index.html
 
no changes added to commit (use "git add" and/or "git commit -a")

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突,或者使用其他第三方工具来解决。

当你解决完所有冲突后再使用 git status 会显示冲突已解决,但目前仍在合并操作当中,需要你手动进行合并提交:

$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)
 
Changes to be committed:
 
    modified:   index.html

如果你对结果感到满意,并且确定之前有冲突的文件都已经暂存了,这时你可以输入 git commit 来完成合并提交。 默认情况下提交信息看起来像下面这个样子:

Merge branch 'iss53'
 
Conflicts:
    index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#	.git/MERGE_HEAD
# and try again.
 
 
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#	modified:   index.html
#

如果你觉得上述的信息不够充分,不能完全体现分支合并的过程,你可以修改上述信息, 添加一些细节给未来检视这个合并的读者一些帮助,告诉他们你是如何解决合并冲突的,以及理由是什么。