如何在git中合并两个具有不同目录结构的分支?

81

我在一个Web应用程序项目中开始使用Maven,因此目录层次结构改变了。我为Maven集成创建了一个新的分支。现在我有两个分支,一个是旧的目录层次结构,另一个是Maven目录层次结构。这两个分支都有新的提交(错误修复和新功能)。

我想摆脱旧分支,并将其更改合并到Maven分支中。Git合并会产生数不清的冲突,感觉无法解决。我认为这是因为文件路径已更改。

如何最好地处理此合并?


10
其他读者需知:这类问题的典型错误信息是“太多的文件跳过不精确的重命名检测”。 - Nils Werner
2个回答

176
尝试将此合并的 merge.renameLimit 设置为较高的值。 Git 尝试检测重命名,但仅当文件数量低于此限制时才这样做,因为它需要 O(n ^ 2)处理时间。
git config merge.renameLimit 999999

然后完成时:

git config --unset merge.renameLimit

8
在增加了renameLimit之后,我不得不运行"git merge --abort"以便重新尝试pull操作。除此之外,一切都很顺利。 - leontx

27

这篇博客文章 "Confluence, git, rename, merge oh my… " 提供了一些有趣的信息,阐述了 Robie回答(已经获得投票):

当试图检测重命名时,git会区分精确和不精确的重命名

  • 前者是无需更改文件内容的重命名;
  • 后者是可能包含文件内容更改的重命名(例如,移动Java类的名称)。

这种区别很重要,因为用于检测精确重命名的算法是线性的,并且总是会执行,而用于检测不精确重命名的算法是二次的(O(n^2)),如果更改的文件数量超过某个阈值(默认值为1000),则git不会尝试执行此操作。

当未显式设置时,merge.renameLimit 默认为1000个文件,或者如果设置,则使用diff.renameLimit的值。
diff.renameLimit影响git diffgit showgit log,而merge.renameLimit仅适用于合并尝试(git mergegit cherry-pick)。

更改merge.renameLimit是个好主意,而不是更改diff.renameLimit,这样git在查看git diff输出之类的常见操作时就不会尝试查找重命名。

要显示重命名,可以使用像git showgit log这样的命令,并开启检测重命名的-M选项。

Linus提到

是的,对于内核,我有

   [diff]
           renamelimit=0

如果想要完全禁用限制,因为默认的限制非常低。Git对于重命名检测非常擅长。

然而,默认设置为低限制并不是因为它运行得不够快,而是因为它可能会使用大量内存(如果你的内存较低,则会导致交换操作,变得“像糖蜜一样缓慢” - 但它仍然不会受到CPU限制,只是疯狂分页)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接