如何审查合并的提交

阅读数:506 2014 年 3 月 6 日

话题:语言 & 开发架构

近日,苹果公司新发布的iOS 7.0.6一度闹得沸沸扬扬,这是由于它修复了一个因 goto 而引起的 bug。对于广大开发者来说,这个 bug 出现的原因以及如何避免其出现,成了热议的话题。

知名博主陈皓分享了他对于该事件的思考。他认为这可能是代码在合并过程中导致的 bug,而这种 bug 却很难在代码审查时被发现。

前微软工程师,现就职于GithubPhil Haack在其博客中分享了他的团队是如何审查合并提交的。在此前,他们的合并流程是这样的(假设要将 master 分支合并到 long-running-branch 分支上):

  1. 在 long-running-branch 分支上创建一个新的分支:merge-master-into-long-running-branch。
  2. 在该分支上执行合并。
  3. 将该分支推送(push)到 Github 上。
  4. 根据该提交创建一个拉请求(pull request),请团队其他人进行审查。

在 git 中,这相当于执行下面的命令集:

git checkout long-running-branch
git checkout -b merge-master-into-long-running-branch
git merge master
# Manually do a lot of work to resolve the conflicts and commit those changes
git push origin merge-master-into-long-running-branch

然而这样的方式可能会产生问题。Phil 的同事Paul Betts指出,在将一个分支合并到另一个的时候,该合并提交的 diff 将显示从最后一次合并之后的所有改变。这很可能是已经审查过的代码。而我们真正想要看到的,是这次提交是否有冲突,以及如何解决这些冲突。

参与LibGit2开发的Russell Belfer给出了答案。

在将一个分支合并到另一个分支时,会在这两个分支上各创建一个合并提交。以SignalR一次合并提交为例。该提交要将 release 分支合并到 dev 分支,该提交的 SHA 为 cc5b002a5140e2d60184de42554a8737981c846c,以 cc5b002a 代替。

我们可以使用 git diff 命令,从两个父分支上分别查看这个合并。例如:

git diff cc5b002a^1 cc5b002a
git diff cc5b002a^2 cc5b002a

如果只想查看冲突的部分,可以使用 git show 命令:

git show --cc cc5b002a

git show 所展示的内容,要比整个合并提交的 diff少得多,因为 --cc 选项可以忽略没有冲突的部分,即只显示与该提交的所有父分支都不相同的部分。这样,审阅者就可以更加专注于冲突的部分,从而降低 bug 发生的概率。

Phil 在文章最后介绍了他是如何发现这样一个合并冲突的示例的。他执行了 git log --min-parents=2 -p --cc 命令,从而找出了至少有两个父分支的提交。