应该在 git 上使用默认的冲突风格吗?

最近我启用了 dev3,现在解决冲突要容易得多。

以前在一些情况下,我必须检查日志,看看为什么人们这样做,这样做的合并。但是,与差异3的信息都显示在一个地方

<<<<<<< HEAD
THIS IS USEFUL
||||||| merged common ancestors
This is useful
=======
This is really useful
>>>>>>> c2392943.....

由此我们可以很容易地看到,结果应该是“这是真正有用的”

我想知道是否有任何差异3的缺点? 为什么它不是 git 的默认行为?

21554 次浏览

其他读者(包括 从这篇文章) :

Git 有一个以 diff3格式显示合并冲突的选项(默认情况下,它只显示要合并的两个文件)。你可以这样启用它:

git config --global merge.conflictstyle diff3

实际上没有理由不启用 dev3样式,因为您经常需要祖先来确定正确的 merge 是什么。

这是引入了 相当早(2008年),我认为它不是默认值,因为默认的 Unixdiff不会显示为3路差异。

连同 Git 2.35,你也有 < strong > zdiff3 (「 热心的差异3」)。


正如前面提到的 在这个帖子里,如果您想在不设置配置的情况下运行这个命令,这样您就可以很容易地在普通差异和差异3之间切换,这在一个特定的情况下是可能的:

如果在索引中标记了冲突(即,在冲突合并之后,但在标记路径为已解决之前,您处于的状态) ,您可以这样做:

git checkout --conflict=diff3 <path...>

注意,这实际上是将索引内容签出到工作树中,因此您对冲突的工作树副本所做的任何编辑都将被覆盖。


请注意,|||||| merged common ancestors将随着 git 2.24(2019年第四季度)而发展

参见 提交 B657047(2019年10月7日) ,第八季,第33集(2019年10月1日)和 提交4615a8c提交45ef 16f提交 f3081da第五季,第57集犯罪现场调查,第95季,第481集犯下779fb8提交8599ab4提交 B6570470,提交 B6570471,提交 B6570472,提交 B6570473,提交 B6570474,提交 B6570475,提交 B6570476,提交 B6570477,提交 B6570478,提交 B6570479,第八季,第33集0(2019年8月17日)。
(由 朱尼奥 · C · 哈马诺 gitster于2019年10月15日在 280bd44合并)

merge-recursive : 为差异3的共同祖先提供一个更好的标签

由 Elijah Newren 签名

提交7ca56aa07619(“ merge-recursive: 添加祖先的标签”,2010-03-20,Git v1.7.1-rc0—— 合并)中,为‘ ||||||’行添加了一个标签,使其具有更多信息的标题‘ |||||| merged common ancestors’,声明如下:

如果能用一个信息量更大的标签就更好了。
也许有一天会有人提供一个。

当递归性发挥作用时,即当存在多个合并基时,所选择的标签是完全合理的。

(在这种情况下,我想不出更好的标签了。)

但是,当存在唯一的合并基或没有合并基时,这实际上有些误导。

根据合并基数更改此选项:

>=2: "merged common ancestors"
1:   <abbreviated commit hash>
0:   "<empty tree>"

我们还添加了一些测试,以检查我们是否为这三种情况中的每一种获得了正确的祖先名称。


使用 Git 2.25(2020年第一季度) ,“ git apply --3way”学会了遵守 merge.conflictStyle配置变量,就像合并一样。

提交091489d犯罪提交9580620提交 b006968提交 fa87b81(2019年10月23日) by 刘(Denton-L)
(由 朱尼奥 · C · 哈马诺 gitster于2019年11月10日在 承认吧合并)

apply : 在 -3 way 中尊重 merge.contentStyle

签名: Denton Liu

以前,当进行3路合并时,merge.conflictStyle选项没有得到尊重,即使指定了“ diff3”,也总是使用“ merge”样式。

git_apply_config()的末尾调用 git_xmerge_config(),以便读取 merge.configtStyle 配置。

为什么它不是 git 的默认行为?

我认为它不是默认的,因为 git mergetool在顶部显示了3个面板: 本地,基地(共同祖先)和远程 + 第4面板在底部,其中有你写在你的问题的内容。

因此,如果打开 diff3并使用 mergetool,那么在顶部中间面板和底部面板中的 | | | | | | | | 和 = = = = = = = = 之间的部分中就会有重复的信息。

diff3应该是默认值。它不仅有助于解决冲突,它使解决冲突 有可能。使用(仅)默认合并正确解决冲突几乎是不可能的 我建议每个人在他们的全局选项中设置 diff3

git config --global merge.conflictStyle diff3

为什么从字面上看是不可能的? 考虑一个分支,它增加了一个 函数 foo1在特定的源文件位置

def foo1():
print("foo1")

以及在同一位置增加函数 foo2的另一个分支

def foo2():
print("foo2")

如果我将其中一个重新设置为另一个,我会得到一个冲突。默认合并 冲突风格会显现出来

++<<<<<<< HEAD
+def foo1():
+    print("foo1")
++=======
+ def foo2():
+     print("foo2")
++>>>>>>> Add foo2

冲突标记告诉我什么? 他们告诉我 需要 foo1foo2的文件,对不对? 不幸的是没有! 考虑一个 foo1foo2已经存在的文件 存在,并且有两个分支,其中一个去除 foo1,另一个去除 foo1 移除 foo2。如果我将其中一个重新基于另一个,结果是什么 将显示默认的合并冲突样式

++<<<<<<< HEAD
+def foo1():
+    print("foo1")
++=======
+ def foo2():
+     print("foo2")
++>>>>>>> Remove foo1

在默认冲突样式下,删除两个函数的情况是 与增加两个函数的情况完全无法区分 (除了提交消息的文本只能是 (提示) ! 因此它不足以用于 解决冲突。这可能解释了为什么解决冲突 被看作是一种黑暗的艺术。 diff3不仅使它成为可能,而且常常使它变得容易。

默认合并冲突风格的另一个竞争者: zdiff3,从 Git 2.35(Q12022)开始: “ 狂热的 diff3”风格的合并冲突表示已经被添加。

提交 ddfc44a(2021年12月1日) by Elijah Newren (newren)
提交4496526(2021年12月1日) by 菲利普 · 伍德(phillipwood)
(由 朱尼奥 · C · 哈马诺 gitster于2021年12月15日在 提交4ce498b合并)

xdiff : 实现一个热心的 dev3,或“ zaff3”

基于补丁的: Uwe Kleine-König
合著者: Elijah Newren
签名: 菲利普 · 伍德
由 Elijah Newren 签名

与普通 diff3完全相同,只是它允许在冲突主体的开始或结束处压缩历史两侧的共同线。
例如,以下 diff3冲突:

1
2
3
4
<<<<<<
A
B
C
D
E
||||||
5
6
======
A
X
C
Y
E
>>>>>>
7
8
9

在两边有共同的线‘ A’、‘ C’和‘ E’。
使用 zdiff3,会得到以下冲突:

1
2
3
4
A
<<<<<<
B
C
D
||||||
5
6
======
X
C
Y
>>>>>>
E
7
8
9

请注意,公共行“ A”和“ E”被移到冲突之外。

与“合并”conflictStyle中的双向冲突不同,zdiff3冲突不会被分割成多个冲突区域,以便在冲突之外显示常见的“ C”行,因为 zdiff3也显示了基本版本,而基本版本不能被合理地分割。

还需要注意的是,删除双方共有的行可能会使冲突区域内的剩余文本与冲突区域内的基本文本相匹配(例如,如果 diff3冲突在冲突的右侧有“ 5 6 E”,那么公共行“ E”将被移到外部,基本和右侧的剩余冲突文本将是行“ 5”和“ 6”)。
这有可能使用户感到惊讶,并使他们认为不应该存在冲突,但肯定存在冲突,应该继续存在。

虽然我必须说我非常喜欢区别,但有一个缺点是,有时冲突往往比那时更大。

当然,更改新特性的默认值会让人们感到困惑。