为什么在3路合并提交中需要共同的祖先?

时间:2016-05-03 22:51:44

标签: git

我正在阅读this

  

在这种情况下,Git使用两者进行简单的三向合并   分支提示指向的快照和共同的祖先   2。

3-way

  

典型合并中使用的三个快照。图3-16。三个快照   用于典型的合并而不仅仅是移动分支指针   转发,Git创建一个由这个三向产生的新快照   合并并自动创建指向它的新提交。这个   被称为合并提交,并且特别在于它具有更多   而不是一个父母。

这两个提示有意义......但为什么你需要共同的祖先?

3 个答案:

答案 0 :(得分:2)

Git需要知道每个分支中发生了什么变化,所以让我们说master更改文件A,iss53更改文件B.没有找到共同的祖先,Git只会知道这两个文件A和B在提示中有所不同,但不能选择哪个版本的A和B.

通过将提示与共同祖先进行比较,Git可以可靠地看到A iss53没有变化,因此使用master的A版本,反之亦然。“ p>

当两个分支修改同一个文件时,事情会变得更复杂,但这应该澄清事情。

答案 1 :(得分:1)

如果您查看three-way merge的实际含义,则应该更清楚地了解共同祖先。

使用图中的节点标签,假设您的仓库有一个文件foo

在提交C2(共同祖先)中,foo包含:

a
b
c

在提交C4中,foo更改为:

aa
b
c

在提交C5中,foo更改为:

a
b
cc

合并C4C5应该没有冲突,导致:

aa
b
cc

以第1行为例,在不考虑共同祖先的情况下,Git只会知道此行在提交C4C5之间是不同的,但不会知道哪个版本(aaa)应保留在合并结果中,因此Git必须将其标记为合并冲突。为了解决冲突,用户必须将在共同祖先出现的foo与在fooC4中出现的C5进行比较。由于第1行仅在其中一项提交(C4)中进行了更改,因此应保留更改(aa)。通过考虑共同祖先,Git可以自动执行此步骤。

如果C5也更改了第1行(例如,更改为aaaa),那么Git不会知道最好保留哪个版本。这将导致用户需要手动解决的合并冲突。

答案 2 :(得分:-1)

主要原因是因为git没有合并tip-to-tip。相反,它以递增方式合并分支到分支。含义:它分别合并每个分支中的每个提交。

在上面的示例中,git不直接合并C4和C5。相反,它首先合并C3和C4,然后它合并C5和C4。为了做到这一点,它必须找出它开始合并的位置。它是从C0开始的吗?它是以C1开始的吗?确定从哪里开始合并的过程就是寻找共同的祖先。

为什么git以这种方式合并?

因为事实证明它是以最少的合并冲突*结束的技术。以前的源代码控制系统只执行diff-patch进程,这往往会产生大量的合并冲突。

*注意:事实上,git使用的确切算法(合并顺序)是作为插件实现的,因此您可以自由选择多种算法,以根据您的工作流程减少合并冲突。