【问题标题】:How can I make git merge produce more granular conflicts when using `merge.conflictstyle diff3`?使用 `merge.conflictstyle diff3` 时,如何使 git merge 产生更细粒度的冲突?
【发布时间】:2022-01-19 00:14:15
【问题描述】:

在我看来,我对 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。这可行,但相当烦人。

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

【问题讨论】:

  • 这个问题是 diff3 merge.conflictStyle 特有的。没有它,它会做你想做的事。
  • @Schwern 是的,但是我不会享受 diff3 冲突风格的好处。在这个简单的例子中,这无关紧要,但总的来说,我想坚持 diff3 冲突风格。
  • 我已经把它归结为一个简单的解释为什么你不能同时拥有它。

标签: git merge version-control


【解决方案1】:

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 将其更改为添加了五行。功能增加了五行。这是三向冲突的正确表示。

让我们看看你期望看到什么......

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

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

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

# ancestor
line1
line2
line4
line5

# main
line1
line2
line3
line4
line5

# feature
line1
line2
line
line4
line5

这不是真的,祖先是空白的。

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

【讨论】:

  • 我想这可以解释为什么 diff3 会这样。在那种情况下,我希望看到另一种冲突风格,它能给我我想要的东西。我认为我建议的冲突风格没有根本问题。
  • 您建议的冲突风格没有根本问题。默认样式只显示两个提示中的不同行,diff3 样式显示两个提示中的不同变化,您想要混合。我认为所有合并工具都已经向您展示了在类固醇上,所有四个版本(基础、我们的、他们的、冲突的)都适当地突出了不同的行。但有时你确实需要一个 diff3,显示每个提示的全部变化。
  • @ntv1000 你需要更灵活的东西。一个好的 IDE(Visual Studio Code、Atom、JetBrains)会有自己的可视化合并冲突工具。或者您可以使用git-mergetool 选择任意数量的现有合并实用程序来解决冲突。请参阅Customizing Git 中的“外部合并和差异工具”。
  • 有人正在研究第三种合并冲突显示算法,暂时称为“zdiff3”,它可以让 Git 尽其所能并以 diff3 样式显示剩余的差异。我不知道它是否会处理这种特殊情况。
猜你喜欢
  • 2019-05-18
  • 2015-10-02
  • 2013-06-04
  • 1970-01-01
  • 2013-10-27
  • 2019-01-11
  • 2015-02-09
  • 1970-01-01
  • 2013-12-30
相关资源
最近更新 更多