diff3 应该是 git 上的默认冲突样式



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

以前在某些情况下,我必须检查日志以查看人们为什么这样做和那样进行合并。但是使用 diff3,信息都显示在一个地方

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

由此我们可以很容易地看到结果应该是"这真的很有用">

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

对于其他读者(以及本文(:

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

git config --global merge.conflictstyle diff3

您真的没有理由不启用 diff3 样式,因为您经常需要祖先来确定正确的合并是什么。

这是很早就引入的(2008 年(,我想它不是默认的,因为默认的 Unix diff不会显示为 3 向差异。

在 Git 2.35 中,你也有zdiff3 (">热心的 diff3"(。

<小时 />

如此线程中所述,如果您想在不设置配置的情况下运行此命令,以便您可以轻松地在普通 diffs 和 diff3s 之间切换,这在一种特定情况下是可能的:

如果在索引中标记了冲突(即,冲突合并后但在将路径标记为已解决之前所处的状态(,则可以执行以下操作:

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

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

<小时 />

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

请参阅提交 b657047(2019 年 10 月 7 日(、提交 8e4ec33(2019 年 10 月 1 日(和提交 4615a8c、提交 45ef16f、提交 f3081da、提交 5bf7e57、提交 e95e481、提交 a779fb8、提交 8599ab4、提交 7c0a6c8、提交 c749ab1、提交 bab5687、提交 ff1BFA2、提交 4d7101e、提交 724dd76、提交 345480d、提交 b4db8a2、提交 98a1d3d、提交 9822175、提交 10f751c (2019 年 8 月 17 日((newren (.
(由Junio C Hamano -- gitster -- 在提交 280bd44 中合并,2019 年 10 月 15 日(

merge-recursive:为diff3共同祖先提供更好的标签

签名:以利亚·纽伦

在提交 7ca56aa07619 (" merge-recursive : 为祖先添加标签", 2010-03-20, Git v1.7.1-rc0 -- merge( 中,为"||||||"行添加了一个标签,使其具有更具信息性的标题 ' |||||| merged common ancestors ',并带有以下语句:

最好使用信息量更大的标签.
也许有一天有人会提供一个。

当递归性开始时,即当有多个合并基础时,这个选择的标签是完全合理的。

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

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

根据合并基数更改此设置:

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

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

<小时 />

在 Git 2.25(2020 年第 1 季度(中,"git apply --3way "学会了像合并一样尊重merge.conflictStyle配置变量。

请参阅提交 091489d、提交 aa76ae4、提交 9580620、提交 b006968、提交 fa87b81 (2019 年 10 月 23 日(,作者:Denton Liu ( Denton-L (.
(由Junio C Hamano -- gitster -- 在提交eff313f中合并,2019年11月10日(

apply : 尊重 merge.conflictStyle in --3way

签约人:刘丹顿

以前,在进行 3 向合并时,不尊重 merge.conflictStyle 选项,并且始终使用"merge"样式,即使指定了"diff3"。

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

默认合并冲突样式的另一个竞争者: zdiff3 ,从 Git 2.35(2022 年第 1 季度(开始:">热心diff3"样式的合并冲突表示已添加。

参见提交 ddfc44a (01 Dec 2021( by Elijah Newren ( newren (.
参见菲利普·伍德(phillipwood(的提交4496526(2021 年 12 月 1 日(.
(由 Junio C Hamano -- gitster -- 合并于 提交 4ce498b,2021 年 12 月 15 日(

xdiff:实现一个热心的 diff3,或"zdiff3">

Based-on-patch-by: Uwe Kleine-König<</sup>br/>合著者:Elijah Newren
签名者:菲利普·伍德
签名:以利亚·纽伦

"zdiff3"与普通diff3相同,只是它允许在冲突开始或结束时压缩历史双方的共同线 hunk.
例如,以下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"><(。这有可能让用户感到惊讶,让他们认为不应该有冲突,但肯定有冲突,应该继续存在。

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,另一个删除删除foo2 。 如果我在另一个上重新定位一个,结果是什么? 这将显示默认合并冲突样式

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

在默认冲突样式下,删除两个函数的情况是与添加两个功能的情况完全没有区别(除了提交消息的文本,它只能是一个提示(! 因此,它不足以达到以下目的解决冲突。 这可能解释了为什么解决冲突被视为一种黑暗艺术。 diff3不仅使它成为可能,而且往往使它变得容易。

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

我认为这不是默认的,因为无论如何git mergetool顶部显示 3 个面板:本地、基础(共同祖先(和远程 + 底部的第 4 个面板,其中包含您在问题中写的内容。

因此,如果您打开diff3并使用mergetool,则会在中间顶部面板以及底部面板中的 |||||||| 和 ======= 之间的部分中复制信息。

虽然我必须说我非常喜欢 diff3,但一个缺点是冲突有时会更大。

当然,更改新功能的默认值可能会使人们感到困惑。

最新更新