Git merge diff3风格需要解释

min*_*gle 31 git merge branching-and-merging

我已经合并了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
Run Code Online (Sandbox Code Playgroud)

Edw*_*son 42

您在此示例中看到的内容(带Temporary merge branch标记)是diff3与纵横交错合并冲突的结果.我将用一系列定义来解释这一点.

定义

  • merge base:最近两个合并分支的提交.发生合并冲突时,对两个分支中的相同行进行了不同的更改.该合并基础包含那些什么都行之前任一分支改变了他们.
  • 合并共同的祖先:diff3输出一个额外的"中间"部分,显示合并基础中的行.这是两个分支的起点.
  • 交叉融合:一种合并历史,其中两个分支以一种不可能是快速合并的方式相互合并.我举一个例子如下.在纵横交错的情况下,有多个合并基础.
  • 临时合并分支:当存在多个合并基础时,diff3尝试将它们合并在一起(使用临时合并分支)以形成在diff3的中间部分中显示的单个共同祖先.当没有冲突时,这可以无缝地工作,但是当存在冲突时,您会在中间合并的共同祖先部分中看到临时合并分支的冲突标记.

示例纵横交叉合并冲突场景

只要两个分支在不同的时间点彼此合并,就会发生纵横交错.

m3 *
   |\
   | \
   |  * B1
   |  |
m2 *  * B0
   |\/|
   |/\|
m1 *  * A
   | /
   |/
m0 *
Run Code Online (Sandbox Code Playgroud)

考虑这一系列事件:

  • m0作为origin/m aster 存在
  • feature-A用一个提交创建一个功能分支A
  • m1 被其他人承诺掌握
  • 我开始一个新的特性分支feature-B是建立在A
  • 我合并origin/master(m1)到feature-B.它冲突,我解决它.合并提交是B0.
  • 我实现了功能-B并将工作提交为B1.
  • feature-A准备发货,所以有人将其合并master.它有冲突.他们解决了这个问题,但他们的分辨率与分辨率不同B0.合并提交是m2.
  • feature-B准备发货,所以有人将其合并master.混帐尝试确定合并基础,但m1A二者作为合并基地同样晋级.git合并m1A临时合并分支中,这会导致冲突.我们在合并的共同祖先部分看到diff3输出,类似于OP的问题.

读取输出

关闭diff3,这个合并冲突看起来就像这样:

<<<<<<< HEAD
    aaaaaa
=======
    hhhhhh
>>>>>>> mybranch
Run Code Online (Sandbox Code Playgroud)

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

与合并的共同祖先冲突模糊

aaaaaahhhhhh,那好一点.;-)

在两个冲突解决方案相互冲突的情况下,aaaaaa并且hhhhhh是两个决议.

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

合并共同的祖先冲突,分组

有了这个特定的合并历史,有超过2个合并基础,这需要多个临时合并分支,然后合并在一起.当存在许多合并基础和冲突时,结果可能变得非常毛茸茸且难以阅读.有人说不要打扰,只是为这些情况关闭diff3.

还要注意git内部可能决定使用不同的合并策略来自动解决冲突,因此输出很难理解.如果可以,请理解它,但要知道它不是供人类消费的.在这种情况下,合并mybranch到和Temporary merge branch 1之间时发生冲突.Line 在临时合并分支之间没有冲突.然后合并时发生了冲突单独成,多的共同祖先.已经通过合并解决冲突和如,但删去(或移动)的线(因而之间没有线解决了冲突相同和.bbbbbbccccccddddddTemporary merge branch 2HEADHEADffffffggggggeeeeeeTemporary merge branch 2======Temporary merge branch 2

你如何解决这样的冲突?虽然技术分析是可能的,但您最安全的选择通常是回过头来查看冲突周围所有相关分支的历史记录,并根据您的理解手动制定分辨率.

避免这一切

这些冲突是最糟糕的,但有一些行为将有助于防止它们.

  1. 避免纵横交错合并.在上面的示例中,feature-B合并origin/masterB0.这种合并可能与主人保持同步是不必要的(虽然有时候是这样).如果origin/master从未合并过feature-B,那么就没有合并纵横交错,并且作为唯一的合并基础m3将是一个正常的冲突A.

    m3 *              m3 *
       |\                |\
       | \               | \
       |  * B1           |  * B1
       |  |              |  |
    m2 *  * B0   VS   m2 *  |
       |\/|              |\ |
       |/\|              | \|
    m1 *  * A         m1 *  * A
       | /               | /
       |/                |/
    m0 *              m0 *
    
    Run Code Online (Sandbox Code Playgroud)
  2. 与冲突解决方案保持一致.在该示例中,仅发生临时合并基础冲突,因为m2并且B0具有不同的冲突解决方案.如果他们以相同的方式解决了冲突,那m3将是一个干净的合并.虽然这是一个简单的纵横交错合并应该具有相同的分辨率.其他情况可能正确地具有不同的分辨率.当合并点之间有两个以上的合并基础和多次提交时,事情变得更加复杂.也就是说,如果你故意在纵横交错的情况下与冲突解决方案不一致,那么以后会出现令人头疼的问题.

  • 嗯,您添加了两次相同的答案?:http://stackoverflow.com/a/33419598/456814。 (2认同)