【问题标题】:Should diff3 be default conflictstyle on git?diff3 应该是 git 上的默认冲突样式吗?
【发布时间】:2015-02-09 15:07:33
【问题描述】:

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

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

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

从中我们可以很容易地看出结果应该是“这真的很有用”

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

【问题讨论】:

  • 我认为它绝对应该是默认值。顺便说一句,这个例子很好,说明性很强。
  • 不能再同意了。

标签: git git-diff diff3


【解决方案1】:

对于其他读者(和from this article):

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

git config --global merge.conflictstyle diff3

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

这是 fairly early (2008) 引入的,我想它不是默认值,因为默认的 Unix diff 不会显示为 3 路差异。

Git 2.35, you also have zdiff3(“热心diff3”)。


in this thread 所述,如果您想在不设置配置的情况下运行此命令,以便在普通差异和差异3 之间轻松切换,这在一种特定情况下是可能的:

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

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

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


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

参见commit b657047(2019 年 10 月 7 日)、commit 8e4ec33(2019 年 10 月 1 日)和 commit 4615a8ccommit 45ef16fcommit f3081dacommit 5bf7e57commit e95e481commit c749ab1、@9876 ,commit 7c0a6c8commit c749ab1commit bab5687commit ff1bfa2commit 4d7101ecommit 724dd76commit 345480dcommit b4db8a2commit 98a1d3d,@987654343(187654343)(187654343) Elijah Newren (newren).
(由 Junio C Hamano -- gitster -- 合并于 commit 280bd44,2019 年 10 月 15 日)

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

签字人:Elijah Newren

commit 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 年第一季度),“git apply --3way”学会了尊重 merge.conflictStyle 配置变量,就像合并一样。

参见Denton Liu (Denton-L)commit 091489dcommit aa76ae4commit 9580620commit b006968commit fa87b81(2019 年 10 月 23 日)。
(由Junio C Hamano -- gitster -- 合并到commit eff313f, 2019 年 11 月 10 日)

apply: 尊重 --3way 中的 merge.conflictStyle

签字人:Denton Liu

之前,在进行 3 路合并时,merge.conflictStyle 选项不受尊重,并且始终使用“merge”样式,即使指定了“diff3”也是如此。

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

【讨论】:

  • 感谢您的回答。我想知道为什么他们在最新版本的 git 中不将其设置为默认值?
  • 我认为是因为 Git 的 linux 起源:默认情况下,来自 Git 的 diff 的行为类似于 linux diff。
  • 您的第一行显示“来自本文”,但没有链接。
  • @Wildcard 你是对的。我已经添加了缺少的链接。谢谢。
【解决方案2】:

默认合并冲突风格的另一个竞争者:zdiff3,从 Git 2.35(2022 年第一季度)开始:“Zealous diff3”风格的合并冲突呈现已添加。

commit ddfc44a(2021 年 12 月 1 日)Elijah Newren (newren)
请参阅 Phillip Wood (phillipwood)commit 4496526(2021 年 12 月 1 日)。
(由 Junio C Hamano -- gitster -- 合并于 commit 4ce498b,2021 年 12 月 15 日)

xdiff:实现一个热心的 diff3,或“zdiff3”

基于补丁作者:Uwe Kleine-König
合着者:Elijah Newren
署名-作者:Phillip Wood
签名人:Elijah Newren

"zdiff3" 与普通的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”行,因为@ 987654347@也显示了基础版本,基础版本无法合理拆分。

另请注意,删除两侧共有的行可能会使冲突区域内的剩余文本与冲突区域内的基本文本匹配(例如,如果 diff3 冲突在冲突的右侧,然后公共行“E”将被移到外面,而底部和右侧的剩余冲突文本将是行“5”和“6”)。
这可能会让用户感到惊讶,并让他们认为不应该发生冲突,但肯定存在冲突并且应该继续存在。

【讨论】:

    【解决方案3】:

    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 不仅使之成为可能,而且通常使之变得容易。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2018-03-28
        • 2015-10-02
        • 1970-01-01
        • 2014-05-20
        • 2022-01-19
        • 2012-03-31
        • 2016-04-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多