git merge文档对这个例子的描述如下:
A---B---C topic
/
D---E---F---G master
然后,“git merge topic”会重放从分支脱离master(E)到当前提交(C)在master之上所做的修改,并在新提交中记录结果、两个父提交的名称以及用户描述修改的日志消息。
我对“replay the changes”这个短语感到疑惑,我几乎找不到其他关于git合并的文章中提到“replay”这个词。
我想象git找到A和合并基之间的变化,应用这些变化,应用B和A之间的差异,应用C和B之间的差异,然后将这一系列的变化合并到一个合并提交中。
如果这是真的,那会发生什么...
A---B---C---I topic
/ \
D---E---F---G---H(merge)---O master
并且我想把master合并到topic中。假设当前分支是topic,“git merge master”。我的每个“git merge-base master topic”的合并基是commitC。
如果我们坚持“重放”修改的故事,那么topic分支是如何获得提交F和G的修改的呢?它是在查找H和C(合并基)之间的差异吗?如果是这样,为什么要重放第一个例子中的一系列修改,而只是查找分支头和合并基之间的差异呢?
3条答案
按热度按时间gojuced71#
我觉得“重播”这个词用得不好:
我想象git找到A和合并库之间的变化,应用该变化,应用B和A之间的差异,应用C和B之间的差异,然后将这一系列的变化合并到一个合并提交中。
这是解释措辞的合理方式。
这不是Git的工作。
结论:措辞很差。
Git * 所做的 * 是找到合并基准1,然后计算从该提交到两个要合并的提交的diff,一个diff对应一个这样的提交。这些diff有效地“跳过”了所有中间工作。
1假设图中只有一个最低的共同祖先,也就是说,如果有多个LCA候选者,下一步取决于合并策略。
-s recursive
(默认)策略处理多个合并基(两个或多个LCA),方法是合并它们并进行新的临时提交。它通过递归调用自身进行合并,因此命名为“递归”。-s resolve
策略处理多个合并基,方法是任意选择一个合并基,并像只有一个合并基一样处理。2实际上是两个或更多,除了某些合并策略处理两个以上的头。具体地说,
-s ours
策略可以使用任意数量的头-但它会忽略除当前头之外的所有头,这意味着它会进行合并提交(作为名词/形容词合并)而不执行任何合并操作-s octopus
策略也可以处理两个以上的头,但是在其他方面比两个头策略更受限制。piv4azn72#
他们在这里使用的描述只是:* 描述性的 *.但这并没有错,真的。
从技术上讲,git只关注三个提交:“我们的”、“他们的”和“合并基础”。合并基础和“他们的”之间的更改将应用到“我们的”,只要它们不与合并基础和“我们的”之间的任何更改冲突。文档将此描述为“重放”更改。这并不意味着每个提交都会在过程中进行检查(la rebase)。
从这个Angular 来看,第二个示例非常简单:base是
C
,“their”是H
,计算C
和H
之间的差,并且将那些改变应用(“重放”)到I
。hl0ma9xz3#
git-merge
man page承认这种潜在的混淆并提供了澄清(着重部分由我加上)
对于使用3路合并的策略(包括默认的ort),如果在两个分支上都进行了更改,但后来在其中一个分支上恢复了更改,则该更改将出现在合并结果中;***这是因为在执行合并时只考虑头文件和合并基文件,而不考虑单个提交.***合并算法因此认为恢复的更改根本没有更改,并替换更改的版本.