git - 导致git merge 冲突的原因和案例有哪些?

标签 git

  • 什么是
  • 充要条件,和/或
  • 所有情况或一些常见情况

  • 这会导致 git merge 报告 merge 冲突吗?
    git merge 如何判断一行或某些行是否包含
    merge 冲突?
  • 例如,我有时会看到类似以下的情况,其中要么Part 1Part 2 为空
    <<<<<<< HEAD
    (Part 1)
    =======
    (Part 2)
    >>>>>>> some-other-branch
    

    对我来说似乎不太可能有 merge 冲突。那么有哪些可能的原因呢?
    像这样的情况有 merge 冲突吗?
  • 比较 git merge 报告的 merge 冲突和git diff 报告的差异,是否正确
  • git diff 报告的差异可能不一定在 git merge
  • 报告的 merge 冲突的地方
  • git merge 报告的 merge 冲突可能不一定在 git diff 报告的差异的地方?

  • 谢谢。

    最佳答案

    完整、正确的答案有多个部分。首先,我们必须首先进行正常的三向 merge (在 Git 中需要使用 -s recursive-s resolve ,如果使用 -s recursive ,则需要找到一个 merge 基础和另外两个提交)。但是,您可能想直接跳到第三部分。

    正常三路 merge 所需的元素

    要进行任何 merge ,您需要:

  • merge 基础提交 B,1
  • 当前提交 L(左侧,又名 HEAD ),以 B 作为祖先,
  • 另一个提交 R 也有 B 作为祖先。

  • 由于“是祖先”允许提交图中的节点相等(从技术上讲,它是前辈或相等的≼比较),因此可能有 B = L 和/或 B = R。但是,如果是这种情况,则不 merge 曾经是必需的,并且如果您确实强制 merge (使用 git merge --no-ff - 这意味着 B = L 和 L ≺ R;这两个非强制情况是“快进”而不是实际 merge 和“没有要 merge 的”错误)不会有 merge 冲突。所以我们也可以假设 merge 基在 merge 的两边之前。

    1使用 --allow-unrelated-histories ,如果 L 和 R 没有最低共同祖先节点,您可以在空树中用 Git 替换实际的基本提交。但是,这会导致所有已识别的文件添加/添加冲突。

    给定 merge ,冲突所需的元素

    接下来,要在某些文件路径中发生冲突,您需要我所说的“高级”冲突或“低级”冲突(或两者)。为此,Git 必须识别(即,匹配在一起)B、L 和 R 中的文件。由于能够添加新文件、重命名文件和删除文件,因此不需要文件具有相同的名称在所有三个提交中。特别是:
  • 如果路径 P 在 B、L 和 R 三个中都存在,则将路径为 P 的三个文件一起标识。 (也就是说,有一个路径 PB,例如 path/to/foo.txt ,它具有匹配的 PL path/to/foo.txt 和 PR path/to/foo.txt 。显然这个文件在整个 merge 过程中都是“同一个文件”,因此 Git 将这三个路径标识为一个文件。)
  • 或者,最多可能有三个不同的路径,PB path/to/basename ,PL path2/to2/left 和 PR path3/to3/right 。其中一项或多项甚至可能不存在。这导致:添加/添加冲突,如果 ∄ PB 和 PL = PR;重命名/删除冲突,如果 PB 等于左或右路径之一,但另一个不存在;或重命名/重命名冲突,如果 PB ≠ PL ≠ PR。

  • 如果尚未存在高级冲突(添加/添加、重命名/重命名或重命名/删除),则可能仍存在重命名/修改或重命名/删除冲突,只要 blob(文件内容)的哈希 ID ) 所命名的两个或三个路径名不匹配。

    所有这些“高级”冲突都会导致 merge 冲突,但它们本身不会导致任何冲突标记。为此,我们现在必须实际将基本文件与两个侧文件 merge (这意味着所有三个文件都必须存在,或者对于添加/添加情况,我们将一个简单的空文件作为基本版本)。

    这种 merge 可能有也可能没有自己的冲突。如果 merge 添加了低级冲突,我们将获得冲突标记。如果没有高级别冲突(所有三个提交中的路径都相同)但需要完全 merge (哈希值都不同),我们可能会遇到带有冲突标记的低级别冲突。

    Git 需要什么才能解决文件中的冲突

    为了在工作树中的一个文件中发生 merge 冲突,Git 必须看到左右版本更改的同一行,但更改方式不同。 (请记住,所有三个哈希值都必须不同,因此 Git 将实际上来自 diff PB PL 的一组更改与来自 diff PB PR 的更改组合在一起。)

    最明显和最不容易混淆的案例

    最明显的情况发生在一侧(让我们先选择左侧)说:
     unchanged context
    -changed line
    +replacement 1
     more unchanged context
    

    另一个说:
     unchanged context
    -changed line
    +replacement 2
     more unchanged context
    

    这里删除一行或多行,取而代之的是插入一行或多行,但插入的行不匹配。在这种情况下,merge 冲突样式将其表示为:
    unchanged context
    <<<<<<< left-label
    replacement 1
    =======
    replacement 2
    >>>>>>> right-label
    more unchanged context
    
    diff3 上下文样式将其表示为:
    unchanged context
    <<<<<<< left-label
    replacement 1
    ||||||| merged common ancestors
    changed line
    =======
    replacement 2
    >>>>>>> right-label
    more unchanged context
    

    如果我们只是添加文本,但在同一行添加不同的文本,也会出现 merge 冲突。同样,来自每一方的添加文本显示在冲突标记中。 (如果我们向两侧添加相同的文本——无论是作为新文本,还是作为更改行的替换文本,Git 都会获取此添加内容的一份副本,不会发生冲突。)

    有点困惑的案例

    如果 一个但不是两个 替换行都是空的——即,如果左侧或右侧差异显示:
     unchanged context
    -changed line
     more unchanged context
    

    然后 缺少 mergediff3 样式标记文件中的替换行之一,但不是全部 。 (如果两个差异都只是删除原始行,则没有冲突:Git 会删除一次。)

    同样,如果一方在另一方删除的行上方或下方添加一行,则会发生冲突。这次冲突显示,保留然后添加a的一侧有所有行,而另一侧没有行。例如:
     some merge conflict.
     Line that will conflict.
    +add line below it
     Rest of the
    

    对比:
     some merge conflict.
    -Line that will conflict.
     Rest of the
    

    (如果您添加上面的行而不是下面的行,也会发生同样的情况)。

    这是 diff3 冲突风格非常有用的地方。以下是这些情况之一的整个 merge 文件:
    We need a base file
    in which to make
    some merge conflict.
    <<<<<<< HEAD
    ||||||| merged common ancestors
    Line that will conflict.
    =======
    Change the line that will conflict.
    >>>>>>> b2
    Rest of the
    base file for the
    merge conflict example.
    

    请注意,现在很明显——或者至少不那么神秘——在基础版本中有一行写着 Line that will conflict.,我从左侧的 HEAD 版本中完全删除了它,并在右侧用不同的行替换b2 版本。

    关于git - 导致git merge 冲突的原因和案例有哪些?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44359334/

    相关文章:

    gitlab-ce 12.X : how do I find the hashed storage path of a repository on the server?

    Git 命令查找分支中不存在于主分支中的提交

    windows - 如何在不杀死其他cmd的情况下杀死一个cmd进程?

    git - 是否推送不属于分支的 Git 提交?

    git - 有没有办法让 git 记住 WebDAV Remote 的密码?

    Github 发布 - 如何部署发布

    git - Jenkins 与 Git : Status code 128

    git - RStudio:git 克隆另一个分支

    git - “go get”不适用于我自己的 git 存储库

    python - 在 Github 提交中强制执行 PEP-8'ish 格式