git merge:如何在BASE文件中出现冲突?

Bal*_*ckk 4 git merge

我在的BASE文件中具有以下内容git merge

<<<<<<<<< Temporary merge branch 1
    - _modifiedTimeWeak = 4.25.2019::11:41:6;
    - _lastID = 3;
    - weakCGTime = 4.25.2019::11:42:20;
    - strongCGTime = 1.2.1990::0:0:0;
=========
    - _modifiedTimeWeak = 5.1.2019::8:52:36;
    - _lastID = 3;
    - weakCGTime = 5.1.2019::8:52:36;
    - strongCGTime = 3.20.2019::17:13:20;
>>>>>>>>> Temporary merge branch 2
Run Code Online (Sandbox Code Playgroud)

我现在已经对该文件进行了无基础的合并,因此没有未解决的问题,但是我想了解可能出了什么问题。

我已经检查了由标识的BASE提交git merge-base,并且它不包括所介绍的合并冲突,因此可以排除。这也是这是第一次,尽管在此存储库发生之前已经进行了许多合并。

可能值得注意的是,我正在使用git merge merge-tool

执行合并时,可能导致BASE文件出现合并冲突的原因是什么,可以采取什么步骤来避免将来发生这种情况?

tor*_*rek 5

行话答案

当存在多个合并库并且合并合并库产生合并冲突时,会发生这些情况。合并基础候选者是您选择要合并的提交的LCA,在提交引起的子图中:

定义3.1。令G =(V; E)为DAG,令x; ÿV。令G x; y是由xy的所有共同祖先集合引起的G的子图。将SLCA(x; y)定义为G x中的出度0节点(叶)的集合;ÿxy的最低共同祖先是SLCA(x; y)的元素。

(请参阅https://www3.cs.stonybrook.edu/~bender/pub/JALG05-daglca.pdf)。这里是在你的仓库中提交,并形成了向无环图XŸ是你选择合并这两个提交。我实际上更喜欢3.2的定义,尽管它使用posets,并且可能更行话:感觉更相关(实际上是用于家谱研究,这是Git在做的事情)。

递归合并策略,-s recursive,使用所有合并基础,合并各合并基础和提交的结果,完成合并冲突,并使用该临时提交的新的合并基础。因此,这就是问题第一部分的答案(“什么可能导致基本文件……发生合并冲突”)。

为避免这种情况,您有几种选择,但是首先让我们更容易地描述问题。

长而有用的答案

您提到您曾经使用过git merge-base。默认情况下,git merge-base选择一个基于最佳合并的提交候选者并打印其哈希ID。如果您git merge-base --all在两个分支技巧提交上运行,则会看到有多个基于最佳合并的提交候选。

在典型的简单分支合并模式中,我们有:

             o--o--o   <-- branch-A
            /
...--o--o--*
            \
             o--o--o   <-- branch-B
Run Code Online (Sandbox Code Playgroud)

通用合并基础-如引用的论文中的3.1或3.2所示;在3.2版本中,您可以从两个分支提示中退回,直到找到在两个分支上都存在的提交为止—当然是提交,*而Git仅需要*分别与分支A和分支B的两个提示提交进行比较。

并非所有的图形都那么简洁明了。获得两个合并基础的最简单方法是在历史链中进行纵横交错的合并,如下所示:

...--o--o--*---o--o--o   <-- branch-C
            \ /
             X
            / \
...--o--o--*---o--o--o   <-- branch-D
Run Code Online (Sandbox Code Playgroud)

请注意,两个已加星标的提交都在两个分支上,并且两个提交都同样接近两个分支提示。运行git merge-base --all branch-C branch-D将打印两个哈希ID。Git应该使用哪个提交作为合并基础?

Git的默认答案是:让我们全部使用它们! Git将运行,实际上:

git merge <hash-of-first-base> <hash-of-second-base>
Run Code Online (Sandbox Code Playgroud)

作为递归(内部)合并。此合并可能会有冲突!

如果合并确实存在冲突,则Git不会停止并从您(用户)那里获得帮助。它只是提交冲突的结果。这成为外部的输入git merge,即您直接要求的输入:

...--o--o--*---o--o--o   <-- branch-C
            \ /
             M   <-- temporarily-committed merge result
            / \
...--o--o--*---o--o--o   <-- branch-D
Run Code Online (Sandbox Code Playgroud)

临时提交实际上不是图中,但对你的外在合并的目的,它也可能是。

如何避免这个问题

现在我们所看到的问题是如何产生的,该如何避免它更清晰,不完全明确,但明确比他们,至少包括:

  • 方法1:避免纵横交错的合并。

    通过避免任何会产生多个合并基础的事情,您永远不会陷入困境。纵横交错的合并是在某种情况下具有branch-Cbranch-D在这种情况下创建的:

           o--o--o   <-- branch-C
          /
    ...--o
          \
           o--o--o   <-- branch-D
    
    Run Code Online (Sandbox Code Playgroud)

    有人-假设某人C-跑来git checkout branch-C; git merge branch-D获得:

           o--o--o---M1   <-- branch-C
          /         /
    ...--o         /
          \       /
           o--o--o   <-- branch-D
    
    Run Code Online (Sandbox Code Playgroud)

    于是,有人,可能是别人,谁没有新的提交上自己的 branch-C ; 让我们称这个人为D -ran git checkout branch-D; git merge <commit that was the previous tip of branch-C before the new merge was just added>,得到:

           o--o--o   <-- branch-C
          /       \
    ...--o         \
          \         \
           o--o--o---M2   <-- branch-D
    
    Run Code Online (Sandbox Code Playgroud)

    C和D共享新提交后,结果是:

           o--o--o---M1   <-- branch-C
          /       \ /
    ...--o         X
          \       / \
           o--o--o---M2   <-- branch-D
    
    Run Code Online (Sandbox Code Playgroud)

    然后定时炸弹被放置了。直到稍后尝试合并提交,它才开始运行,但这就是它的设置。

  • 方法2:如果确实进行此类合并,请小心使用它们 编辑:这实际上并没有帮助:Git仍在使用commit 和之后的提交,并重新合并它们。尽管如此,还是值得考虑一下。我将保留其中一些文本。M1M2

    合并通常都是对称的。注意,当个人C和D运行两个git merge命令时,他们具有相同的提交,从而形成相同的图。它们从相同的合并基础开始,具有相同的两个分支提示提交。通过比较合并基础与每个分支尖端而产生的两个差异是相同的差异。

    因此,人员C和D必须解决一些冲突,就像您在自己的合并合并库中看到的一样。他们可能因此自动完成:例如,人物C可能是碰上git merge -X ours喜欢他的提示提交变化,你发现,在冲突的文件M1,而人d可能运行git merge -X ours到喜欢她的尖提交的变化M2

    这些非对称结果是无害的,除了定时炸弹本身以及您以后进行递归合并的事实。您会看到冲突。再次由您决定解决这个问题,但是这一次,如果对C和D人有用,我们/他们的技巧绝非易事。

  • 方法3(简单但可以说是错误的):使用不同的合并策略。

    递归合并策略,-s recursive是在一个采用此图,发现所有的合并基础提交的考生,如果有一个以上的,将它们合并和使用结果作为输入您的合并。有一种名为resolve-s resolve)的策略,与递归策略共享几乎所有代码。所不同的是,当(或之后)计算的所有合并基地,它只需一个多基地。

    在这种情况下,如果有两个合并候选M1和M2,它们-s resolve只会随机选择M1或M2(实际上不是随机的,无论哪个首先弹出,但控制方式都不是很好:没有明显的理由选择一个vs另一个)。Git将使用这一提交作为合并基础。

    这里的问题很明显:通过使用一个提交(人C或人D),您将忽略另一人选择的冲突解决方案。两人这次离开了您,这枚炸弹给您留下了答案,那-s resolve就是让炸弹摧毁两个结果之一,而我却没有看到谁是正确的,还是应该做些更好的事情

无论如何,都没有一个正确的答案,这与任何合并冲突都是一样的。问题是您现在正在解决一个冲突,该冲突在过去这两个冲突的合并进行时可能应该已经解决了。