我合并了2个分支,出现了冲突,我需要一些提示,从哪里开始到结束,等等。我已经用一些伪造的数据替换了代码,以使其更易于阅读和讨论。

<<<<<<< HEAD
    aaaaaa
||||||| merged common ancestors
<<<<<<< Temporary merge branch 1
    bbbbbb
=======
    cccccc
>>>>>>> mybranch
    dddddd
<<<<<<< HEAD
    eeeeee
||||||| merged common ancestors
    ffffff
||||||| merged common ancestors
    gggggg
=======
>>>>>>> Temporary merge branch 2
=======
    hhhhhh
>>>>>>> mybranch

最佳答案

在本示例中,您看到的(带有Temporary merge branch标记)是diff3带有纵横交错合并冲突的结果。我将用一系列定义对此进行解释。

定义

  • 合并基础:最近合并的两个合并分支脱离的提交。发生合并冲突时,两个分支中的相同行均进行了不同的更改。合并库包含在任一分支更改它们之前这些行的内容。
  • 合并的共同祖先:diff3输出一个额外的“中间”部分,显示合并行中的行。这是两个分支的起点。
  • 交叉合并:合并历史记录,其中两个分支以无法进行快速合并的方式彼此合并。我在下面举一个例子。在纵横交错的情况下,存在多个合并基础。
  • 临时合并分支:当存在多个合并库时,diff3尝试将它们合并在一起(使用临时合并分支),以形成单个公共(public)祖先,以显示在diff3的中间部分。这在没有冲突的情况下可以无缝地工作,但是在存在冲突时,您会在中间合并的共同祖先部分内看到临时合并分支的冲突标记。

  • 纵横交错的合并冲突场景示例

    每当两个分支在不同的时间点相互合并时,就会发生交叉合并。
    m3 *
       |\
       | \
       |  * B1
       |  |
    m2 *  * B0
       |\/|
       |/\|
    m1 *  * A
       | /
       |/
    m0 *
    

    考虑以下事件序列:
  • m0作为原点存在/ m aster
  • 我通过一次提交feature-A
  • 创建功能分支A
  • m1被其他人 promise 掌握
  • 我启动一个新的功能分支feature-B,它基于A
  • 我将origin/master(m1)合并到feature-B中。冲突,我解决了。合并提交为B0
  • 我实现功能B,并将工作提交为B1
  • feature-A已准备好发布,因此有人将其合并为master。发生冲突。他们解决了该问题,但其分辨率与B0中的分辨率不同。合并提交为m2
  • feature-B已准备好发布,因此有人将其合并为master。 git试图确定合并基础,但是m1A都可以等同地作为合并基础。 git在一个临时的合并分支中合并m1A,这导致冲突。我们在合并的公共(public)祖先部分中看到diff3输出,类似于OP的问题。

  • 读取输出

    禁用diff3后,此合并冲突将看起来像这样:
    <<<<<<< HEAD
        aaaaaa
    =======
        hhhhhh
    >>>>>>> mybranch
    

    首先,使用所有其他标记,您将要确定实际的冲突线是什么,因此可以将其与diff3共同祖先输出区分开。

    aaaaaahhhhhh,好一点。 ;-)

    在两个冲突解决方案冲突的情况下,aaaaaahhhhhh是两个解决方案。

    接下来,检查合并的共同祖先的内容。

    在这种特殊的合并历史记录中,有超过2个合并基础,这需要多个临时合并分支,然后将它们合并在一起。当合并基础很多且发生冲突时,结果可能会变得非常冗长且难以阅读。有人说不要打扰,只需在这种情况下关闭diff3。

    另请注意,git内部可能会决定使用不同的合并策略来自动解决冲突,因此输出可能很难理解。如果可以的话,请从中讲解,但要知道它不是供人类食用的。在这种情况下,在mybranchTemporary merge branch 1之间将bbbbbb合并为cccccc时发生冲突。 dddddd行在临时合并分支之间没有冲突。然后,当将Temporary merge branch 2合并到HEAD中时,发生了一个单独的冲突,并带有多个共同祖先。 HEAD通过将ffffffgggggg合并为eeeeee来解决了冲突,但是Temporary merge branch 2通过删除(或移动)行(因此======Temporary merge branch 2之间没有任何行)解决了相同的冲突。

    您如何解决这样的冲突?尽管可能进行技术分析,但是最安全的选择通常是返回并查看冲突周围所有相关分支的历史记录,然后根据您的理解手动制定解决方案。

    避免所有这一切

    这些冲突是最严重的,但是有些行为可以帮助防止冲突。
  • 避免纵横交错的合并。在上面的示例中,feature-Borigin/master合并为B0。可能不需要此合并来保持与master的最新同步(尽管有时是必须的)。如果origin/master从未合并到feature-B中,则不会有合并交叉,并且m3A作为唯一合并基础是正常的冲突。
    m3 *              m3 *
       |\                |\
       | \               | \
       |  * B1           |  * B1
       |  |              |  |
    m2 *  * B0   VS   m2 *  |
       |\/|              |\ |
       |/\|              | \|
    m1 *  * A         m1 *  * A
       | /               | /
       |/                |/
    m0 *              m0 *
    
  • 与冲突解决方案保持一致。在该示例中,仅由于m2B0具有不同的冲突解决方案而发生临时合并库冲突。如果他们以相同的方式解决了冲突,则m3将是干净的合并。请意识到,尽管这是一个应该具有相同分辨率的简单的交叉合并。其他情况可能正确地具有不同的解决方案。当合并基础超过2个并且合并点之间有多个提交时,事情就变得更加复杂。就是说,如果您已知地在纵横交错的情况下与冲突解决方案不一致,请稍后再感到头疼。
  • 07-24 13:30