这会导致
git merge
报告 merge 冲突吗?git merge
如何判断一行或某些行是否包含merge 冲突?
Part 1
或 Part 2
为空<<<<<<< HEAD
(Part 1)
=======
(Part 2)
>>>>>>> some-other-branch
对我来说似乎不太可能有 merge 冲突。那么有哪些可能的原因呢?
像这样的情况有 merge 冲突吗?
git merge
报告的 merge 冲突和git diff
报告的差异,是否正确git diff
报告的差异可能不一定在 git merge
和 git merge
报告的 merge 冲突可能不一定在 git
diff
报告的差异的地方? 谢谢。
最佳答案
完整、正确的答案有多个部分。首先,我们必须首先进行正常的三向 merge (在 Git 中需要使用 -s recursive
或 -s resolve
,如果使用 -s recursive
,则需要找到一个 merge 基础和另外两个提交)。但是,您可能想直接跳到第三部分。
正常三路 merge 所需的元素
要进行任何 merge ,您需要:
HEAD
),以 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 中的文件。由于能够添加新文件、重命名文件和删除文件,因此不需要文件具有相同的名称在所有三个提交中。特别是:
path/to/foo.txt
,它具有匹配的 PL path/to/foo.txt
和 PR path/to/foo.txt
。显然这个文件在整个 merge 过程中都是“同一个文件”,因此 Git 将这三个路径标识为一个文件。)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
然后 缺少
merge
或 diff3
样式标记文件中的替换行之一,但不是全部 。 (如果两个差异都只是删除原始行,则没有冲突: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/