接下来,你得进行紧急修补。我们创建一个紧急修补分支 hotfix
来开展工作,直到搞定(见图 3-13):
$ git checkout -b ‘hotfix’
Switched to a new branch “hotfix”
$ vim index.html
$ git commit -a -m ‘fixed the broken email address’
[hotfix]: created 3a0874c: “fixed the broken email address”
1 files changed, 0 insertions(+), 1 deletions(-)
有必要作些测试,确保修补是成功的,然后回到 master
分支并把它合并进来,然后发布到生产服务器。用 git merge
命令来进行合并:
$ git checkout master
$ git merge hotfix
Updating f42c576…3a0874c
Fast forward
README | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
请注意,合并时出现了“Fast forward”的提示。由于当前 master
分支所在的提交对象是要并入的 hotfix
分支的直接上游,Git 只需把 master
分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。
现在最新的修改已经在当前 master
分支所指向的提交对象中了,可以部署到生产服务器上去了(见图 3-14)。
![在这里插入图片描述](
)
在那个超级重要的修补发布以后,你想要回到被打扰之前的工作。由于当前 hotfix
分支和 master
都指向相同的提交对象,所以 hotfix
已经完成了历史使命,可以删掉了。使用 git branch
的 -d
选项执行删除操作:
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
现在回到之前未完成的 #53 问题修复分支上继续工作(图 3-15):
$ git checkout iss53
Switched to branch “iss53”
$ vim index.html
$ git commit -a -m ‘finished the new footer [issue 53]’
[iss53]: created ad82d7a: “finished the new footer [issue 53]”
1 files changed, 1 insertions(+), 0 deletions(-)
不用担心之前 hotfix
分支的修改内容尚未包含到 iss53
中来。如果确实需要纳入此次修补,可以用 git merge master
把 master 分支合并到 iss53
;或者等 iss53
完成之后,再将 iss53
分支中的更新并入 master
。
分支的合并
在问题 #53 相关的工作完成之后,可以合并回 master
分支。实际操作同前面合并 hotfix
分支差不多,只需回到 master
分支,运行 git merge
命令指定要合并进来的分支:
$ git checkout master
$ git merge iss53
Merge made by recursive.
README | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
请注意,这次合并操作的底层实现,并不同于之前 hotfix
的并入方式。因为这次你的开发历史是从更早的地方开始分叉的。由于当前 master
分支所指向的提交对象(C4)并不是 iss53
分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(C4 和 C5)以及它们的共同祖先(C2)进行一次简单的三方合并计算。图 3-16 用红框标出了 Git 用于合并的三个提交对象:
![在这里插入图片描述](
)
这次,Git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(C6)(见图 3-17)。这个提交对象比较特殊,它有两个祖先(C4 和 C5)。
值得一提的是 Git 可以自己裁决哪个共同祖先才是最佳合并基础;这和 CVS 或 Subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让 Git 的合并操作比其他系统都要简单不少。
![在这里插入图片描述](
)
既然之前的工作成果已经合并到 master
了,那么 iss53
也就没用了。你可以就此删除它,并在问题追踪系统里关闭该问题。
$ git branch -d iss53
遇到冲突时的分支合并
有时候合并操作并不会如此顺利。如果在不同的分支中都修改了同一个文件的同一部分,Git 就无法干净地把两者合到一起(译注:逻辑上说,这种问题只能由人来裁决。)。如果你在解决问题 #53 的过程中修改了 hotfix
中修改的部分,将得到类似下面的结果:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the resu