我是 git 新手,我了解什么是快进合并 [如果两个分支是线性的,只需将指针移动到分支] 但是当涉及到 3 路合并时,我有点困惑,因为为什么 3 路合并需要共同的祖先创建一个新的提交为什么不能取两个分支[我想要合并到的分支(例如:master)和一些想要合并的分支(例如:immediatefix)] 并比较它们并只是进行合并.. 为什么这样做你想要共同的祖先。还有为什么我们需要共同的祖先......
1 回答
它相当简单,归结为 Git 如何存储提交。与其他 VCS 不同,Git 存储整个工作目录的完整快照。因此,在查看单个提交时,您所能看到的只是该提交中内容的确切状态。
其他 VCS(如 Subversion)通常存储差异。因此,修订被存储为先前状态和当前状态之间的差异。因此,在合并时,您只需查看一个修订版即可了解发生了什么,您可以将其应用到其他地方。
另一方面,Git 没有现成的差异。为了能够看到提交中发生了什么,它需要将内容与父提交进行比较。只有这样,它才能产生差异并将其应用到其他地方。因此,对于两个具有共同基础的分支A
,Git 所做的是查看and和and之间的区别。然后它知道每个分支中究竟发生了什么,并可以尝试应用所有更改。这进一步的好处是,正在查看整个更改范围,因此,如果您暂时更改了一个分支中的某些内容,但后来又取消了,那么合并时它不会显示出全部差异。这通常会导致更少的冲突。B
C
A
C
B
C
这同样适用于变基,除了它实际上是以它的名义。当重新定位B
到A
时,您基本上是在重写范围中的所有提交C..B
以A
作为父级。因此,Git 将查看与分支上的第一次提交之间的区别,C
并将其应用于A
. 然后它将查看第一次提交和第二次提交之间的差异并应用它。这种情况一直持续到整个分支被重新设置A
为基础。
这就是我感到困惑的地方,如果 A 有完整快照而 B 有完整快照,我们可以比较 A 和 B,我们可以合并它,那么为什么我们需要公共基础 C?
好吧,让我们为此尝试一个示例。我们将只查看一个文件以使其更容易,但这会发生在存储库中的每个文件上。
假设这是分支 A 中的文件内容:
alpha
beta
gamma
这是分支 B 中的内容:
alpha
gamma
delta
现在合并后的版本会是什么样子?如果您不知道提交实际更改了什么,则无法安全地做出决定。例如,我们可以说,文件最初(在 C 中)只有alpha
和gamma
. 因此,在分支beta
中添加了 A,并在 Bdelta
中添加了。这将导致:
alpha
beta
gamma
delta
或者我们可以假设相反,说文件最初包含所有四行,所以在 Adelta
被删除,在 Bbeta
被删除:
alpha
gamma
或者我们可以说分支 B 实际上从未接触过文件,所以它的状态应该被忽略,而 A 的内容应该被保留。如果分支 A 从未接触过文件,则同样可以反过来应用。
如您所见,拥有这些分支的基础,因此分支的实际差异有助于决定如何解决合并问题。毕竟,我们希望使用分支来独立于其他分支(与其他独立开发线)开发东西,并且只需合并我们所有的更改,而不必再次在合并期间完成所有工作。