到底什么是 Git 三方对比

问题: 为什么我在 gitlab 上提交的MR,代码diff不是两个分支的区别?

带有场景的举例子:

小A 在linke上建立的新的迭代,同时生成了代码分支 dev,然后 A、B两个同学都在这个迭代进行开发。小 A 基于 dev 分支创建了 dev_A 分支,小B基于dev分支创建了dev_B 分支。后来小A将他的变更合并到了 dev 分支,小B在开发过程中由于和master分支有冲突,所以他在本地解决冲突合并了一下 master 分支,然后又合并了一下 dev 分支,然后推送到 antcode 进行 MR,发现MR中代入了 master 的代码,和小A已经提交的代码?why?

抓狂

AntCode 是如何做代码diff的

1
2
3
4
git diff [<options>] <commit>...<commit> [--] [<path>...]
This form is to view the changes on the branch containing and up to the second <commit>, starting at a common
ancestor of both <commit>. "git diff A...B" is equivalent to "git diff $(git merge-base A B) B". You can omit any
one of <commit>, which has the same effect as using HEAD instead.

上面的命令究竟是如何对比的?

既然 "git diff A...B" is equivalent to "git diff $(git merge-base A B) B",那我们先来看看 git merge-base A B,看看这个是个啥?

简单来说就是 找到 A 和 B 的两个的最近的共同祖先,然后在和 B 做比较。

这个时候我们来看下上面那个场景的拓扑图

![git 三方合并](../media/git 三方合并.png)

这个是 小 B 提交了合并到 dev 的 MR,他看到的对比应该是

devdev_B 的共同祖先是 X 节点,所以展示的diff的区别就是 XdevB 最新commit 的区别,所以区别上会带入其他迭代的代码和dev_A的代码。

如何避免这类问题

  1. 每次提交代码都是基于新的分支,这个新分支的建立是基于最新的 dev 分支创建的
  2. 不要主动去合并master然后推送了,等到预发的时候再合并master。