git合并冲突说删除了,但事实并非如此

Ste*_*lly 5 git merge-conflict-resolution

我正在尝试解决git merge(git版本2.9)中的冲突 - 冲突是建议删除"其他"分支中的文件,但事实并非如此.这是一个(相当)简短的可重复配方:

cd /some/new/folder/somewhere
git init

echo 'a on master' > a
git add a
git commit -m 'add a on master'

mkdir f
git mv a f/
git commit -m 'move a to f on master'

git checkout -b hotfix HEAD^

echo 'new content a on hotfix' > a
mkdir f
git add a
git mv a f/
git commit -m 'move a to f on hotfix with different content'

git checkout master
git merge hotfix
Run Code Online (Sandbox Code Playgroud)

Git现在建议在修复程序分支中删除 f/a ,但显然不是这样吗?

CONFLICT (rename/delete): f/a deleted in hotfix and renamed in HEAD. Version HEAD of f/a left in tree.
Automatic merge failed; fix conflicts and then commit the result.
Run Code Online (Sandbox Code Playgroud)

我会期待像这样的f/a的'正常'冲突:

<<<<<<< HEAD
a on master
=======
new content a on hotfix
>>>>>>> hotfix
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么git建议冲突为重命名/删除冲突?

谢谢你的帮助.

LeG*_*GEC 2

很好地提出了问题。

你的例子有一个缺点:

文件a由一行组成,因此编辑这一行意味着“两个文件之间 100% 的差异”。
git重命名检测算法永远不会将两个 100% 不同的文件检测为重命名。

如果你改变你的例子:

  • 在初始文件中写入 4 行a
  • 修改其内容时仅编辑第一个hotfix

合并不会触发任何冲突,并导致包含f/a修补程序修改。


希望这意味着在您的实际场景中,git 所说的情况数量created vs deleted是有限的。

如果手动处理它们是可行的,这将是一种查看常用三向合并的方法:

 # find the merge-base :
 $ git merge-base master hotfix
 3e12717099f3dc7b83b3d267e5cbd580ec8e69a1

 # get the content you expect for "ours", "base" and "theirs" :
 $ git show master:f/a > f/a.ours
 $ git show hotfix:f/a > f/a.theirs

 # here is the manual part : I don't know how to have an automatic detection
 # of the correct base file :
 $ git show 3e12717:a  > f/a.base

 # start a 3-way merge :
 $ meld f/a.ours f/a.base f/a.theirs

 # if you are satisfied with the content in a.base,
 # and want to use it as your new a :
 $ mv f/a.base f/a
 $ git add f/a
Run Code Online (Sandbox Code Playgroud)