Git Merging - 两个分支同时合并会发生什么

时间:2017-10-16 15:16:30

标签: git merge gitlab branch git-branch

我对git的合并有一个不清楚的理解,我想正确理解。

假设我在主分支上有一个文件F,它已经有100个LOC。我从master创建了一个分支A,我写了50个LOC,从第101行到第150行。我创建合并请求以将分支A合并到主服务器。因此,如果将合并分支A,则主服务器上的文件F将具有150个LOC

我们假设分支A尚未合并为主,仍在等待。我从master那里创建了一个新的分支B.我也写了50个LOC,也从第101行到第150行开始(因为分支A还没有合并)。我还为分支B创建了一个MR

如果2个人审核2个MR,会发生什么,并且:

  1. 他们同时合并2个MR? master会不会有冲突,因为两个分支都想合并到第101到第150行?

  2. 如果首先合并分支A,则意味着主分区已经有150个LOC,但是分支B仍然从第101行到第150行开始,因为它是在master仍然有100个LOC时创建的。 B合并时是否也会发生冲突?或者Git如何处理这些?

  3. 提前致谢(我不是一个巨魔,只是想找出一些东西,以防有人提出这个问题)

1 个答案:

答案 0 :(得分:2)

我认为需要澄清一些事情:冲突和合并策略是git本身的概念。 "合并请求",OTOH,是gitlab的概念(和其他repo主机有类似的概念),但对git本身没有任何意义。谈论git可以最好地回答你的问题;所以我们只需知道合并请求是一个工作流程,通过它可以在git中启动合并操作。因此,让我们将您的问题分为两部分:

顺序合并

简短回答:可能会有冲突。

是否会发生冲突取决于合并策略。我的测试表明通常存在冲突,因为git在第101-150行看到了替代变化。由于两组更改都有所增加,我猜你可以设想两组线路的添加没有冲突 - 尽管它是不清楚他们会进入什么样的顺序。你可以使用union合并驱动程序让git尝试这样做。见http://kernel.org/pub/software/scm/git/docs/gitattributes.html

你可以告诉git通过命令行参数以不同的方式解决合并,但由于这些指示适用于整个提交 - 而不仅仅是设置了这个条件的一个文件 - 你通常不会想要。您可以使用.gitattributes来影响git如何仅合并一个文件,如果您可以提前知道该方法何时适用于(整个)文件。

因此,如何更改merge的行为有很多选项 - 如果不知道具体的预期结果,可以在此处详细说明。但通常情况下,根据我的经验,使用默认的合并设置并解决冲突时效果很好。

并发合并

两个合并不可能同时发生"同时#34;在一个单一的回购。如果主机提供某种方式来直接在托管(origin)仓库上开始合并 - 我实际上并不知道有人这样做,但是为了争论 - 那么一个合并就必须完成首先,另一个会看到合并的结果作为起点;所以请看这个答案的前一部分。

可能发生的情况是,一个人可以在一个仓库上执行一次合并,另一个人可以在第二个仓库上执行另一个合并,然后当他们都尝试与远程同步时可能会发生冲突。以及这看起来如何:

(请注意,在此示例中,我假设 true merges - 即如果使用no-ff选项会发生什么。合并图可能更简单,但是如果允许快进合并,结果将与冲突相同。)

所以回购开始于

            B <--(branch_B)
           /
x -- x -- O <--(master)
           \
            A <--(branch_A)

所有提交都包含一个文件。在O中该文件有100行。 AB每个都会在文件末尾添加50行。

现在Alice合并branch_A,Bob合并branch_B,每个都在他们的本地仓库中。所以爱丽丝已经

            B <--(branch_B)
           /
x -- x -- O -- MA <--(master)
           \  /
            A
            ^-(branch_A)

和鲍勃有

            v-(branch_B)
            B
           /  \
x -- x -- O -- MB <--(master)
           \       
            A <--(branch_A)

要分享他们的工作,他们每个人都会尝试pushorigin;就像merge一样,即使他们试图在同一时刻开始推动,也会先在另一个开始之前完成。

所以爱丽丝得到了她的推动,origin更新为看起来就像她的本地。当Bob试图推送时,他收到错误,因为他的master位于master origin之后(或者,我们可以说,origin/master一旦落后pull已经更新,假设是典型的映射。)

所以Bob必须fetch(或mergepush)才能fetch。为了最清楚地说明,我们假设他是 v-(branch_B) B / \ x -- x -- O -- MB <--(master) |\ | MA <--(origin/master) |/ A <--(branch_A) 。现在他已经

pull

并且为了完成origin/master的效果,他需要将master合并到[set()] * n中 - 所以即使这种情况归结为&#34;顺序合并&#34;方案首先涉及。实际上,如果使用快进合并跟踪相同的场景,则很明显&#34;第二次合并&#34;这里需要与&#34;第二次合并&#34;完全相同如果一切都由一个用户在一个仓库中完成。