使用 `merge.conflictstyle diff3` 时如何使 git merge 产生更细粒度的冲突?

How can I make git merge produce more granular conflicts when using `merge.conflictstyle diff3`?

我认为 git(版本 2.31.1)的合并行为不直观。让我用一个小玩具仓库来演示一下。

git init
touch file1
git add file1
git commit -m "Initial commit"
git branch feature

现在我有一个包含空文件和两个分支的提交,mainfeature,指向该提交。现在我将主分支中的文件更改为

line1
line2
line3
line4
line5

并使用

提交更改
git add file1
git commit -m "Change file1"

接下来,我去另一间分店

git checkout feature

把那里的file1改成

line1
line2
line
line4
line5

并再次提交更改

git add file1
git commit -m "Change file1"

生成的提交树如下所示:

* b1beb63 - Change file1 (HEAD -> feature)
| * 32ea83d - Change file1 (main)
|/
* 2952256 - Initial commit

现在我切换回 main 分支并将 feature 合并到 main.

git checkout main
git config merge.conflictstyle diff3
git merge feature

不出所料,file1 中存在冲突。然而,冲突看起来是这样的:

<<<<<<< HEAD
line1
line2
line3
line4
line5
||||||| 2952256
=======
line1
line2
line
line4
line5
>>>>>>> feature

如您所见,git 就像整个文件是一个大冲突。我希望它看起来像这样:

line1
line2
<<<<<<< HEAD
line3
||||||| 2952256
=======
line
>>>>>>> feature
line4
line5

这将更加用户友好。

我发现了一些线程,其中由于行尾不同,人们遇到了类似的问题。 这里不是这种情况,因为我在同一平台上使用相同的编辑器在两个分支中编辑了文件。

我目前针对此类合并的解决方案是通过对两个分支之间的文件进行比较来手动查找更改,即 git diff main:file1 feature:file1。这有效,但很烦人。

有没有什么方法可以让我在这个合并中得到预期的行为?如果不是,有什么好的理由说明这是不可能的吗?

tl;dr 您的预期行为是冲突的无效 diff3 表示。你不能两者兼得。


The original commit explains in excruciating detail。我会尽量总结一下。

让我们看看你的情况。你是从这个开始的。

# ancestor

# main
line1
line2
line3
line4
line5

# feature
line1
line2
line
line4
line5

您要求所有三个文件之间的差异,这就是您得到的结果。

<<<<<<< HEAD
line1
line2
line3
line4
line5
||||||| 2952256
=======
line1
line2
line
line4
line5
>>>>>>> feature

原文件为空白。 HEAD 将其更改为添加了五行。功能添加了五行。这是 3 向冲突的正确表示。

让我们看看您期望看到的...

line1
line2
<<<<<<< HEAD
line3
||||||| 2952256
=======
line
>>>>>>> feature
line4
line5

这表示 原始文件包含 4 行。 HEAD 和功能在 line2 和 line4 之间添加了一行。

换句话说,它说你合并了这些文件。

# ancestor
line1
line2
line4
line5

# main
line1
line2
line3
line4
line5

# feature
line1
line2
line
line4
line5

这不是真的,老祖宗是空白的

你想要的减少对于 2 向冲突标记是好的,但会破坏 3 向冲突标记的点。

Git 2.35.0 将有一个新的冲突样式,它的行为完全符合此处的要求,称为 zdiff3。可以配置为git config merge.conflictstyle zdiff3。添加--global全局配置冲突样式

我用 git 版本 2.35.0.rc0 测试了它,结果如下。

line1
line2
<<<<<<< HEAD
line3
||||||| 59df1b4
=======
line
>>>>>>> feature
line4
line5

完美!