为什么git不能识别以前在合并时检入的重命名 - 合并方向是否重要?

时间:2012-09-21 04:35:53

标签: git merge

我刚刚经历了一个有点痛苦的过程,在功能分支上重命名/重组和重构大型代码库。在此过程中,我进行了几次更改的增量签名,以确保git识别重命名。但是,现在我将这个功能合并到我的开发分支中,看起来Git并没有“记住”这些重命名,而是将它们视为删除/添加。设置不同的重命名阈值似乎没有帮助。

git不应该从之前的提交中知道文件被重命名/移动了吗?

修改 奇怪的是,如果我将dev合并到我的功能分支中,而不是反之亦然,git似乎会识别重命名。我最终做了这个,然后将dev重置为我的功能分支的顶部。在这种情况下,合并的方向是否重要?

2 个答案:

答案 0 :(得分:2)

git实际上并不跟踪重命名 - 它依赖于重命名检测'检测重命名的算法,如Git FAQ

所述
  例如,Git必须与许多不同的工作流程进行互操作   某些更改可能来自修补程序,其中重命名信息可能不会   能得到的。依赖显式重命名跟踪使其无法实现   合并两棵完全相同的树,除了一棵   做它作为补丁(创建/删除),并使用其他一些做到了   试探法。

     

在第二个注释中,跟踪重命名实际上只是一个特例   跟踪内容在树中的移动方式。在某些情况下,您可能会改为   有兴趣在添加或移动功能时查询   不同的文件。仅依靠重新创建此功能的能力   在需要时,Git旨在提供更灵活的方式   跟踪树木的变化情况。

     

然而,这并不意味着Git不支持重命名。该   Git中的diff机器支持自动检测重命名,   这是由' -M'切换到git-diff- *系列   命令。重命名检测机制由git-log(1)和   git-whatchanged(1),例如,' git log -M'将提交   重命名信息的历史记录。 Git也支持有限的形式   合并重命名。分配责任的两个工具,   git-blame(1)和git-annotate(1)都使用自动重命名   用于跟踪重命名的检测代码。

     

作为一个非常特殊的案例,' git log'版本1.5.3及更高版本   ' - 遵循'允许您在给定a时遵循重命名的选项   单一路径。

因此,如果您重构了重命名了一个文件,那么它与旧文件的相似性将非常小,结果statuslog可能表示该文件被删除然后添加。

一些选项可能有助于检测重命名,即使是通过重构:

  • -M<n>

      

    检测重命名。如果指定了n,则它是一个阈值   相似性指数(即              添加/删除与文件大小相比)。例如,-M90%表示git应该考虑a              如果超过90%的文件没有更改,请删除/添加对重命名。

  • -w

      

    忽略空白量的变化。这忽略了空格   行结束,并考虑所有其他              一个或多个空白字符的序列是等价的。

  • -B<n>

      

    将完全重写更改分为删除和创建对。

-B非常有用,因为它可以将文件视为重命名源,即使它们已被更改;例如,如果您将foo.c的90%移至bar.c,则会检测到重命名,但会在foo.c中保留一些功能。

答案 1 :(得分:0)

您可能会违反git配置设置:merge.renameLimit

此设置默认值非常低(与大型代码库相比),并且如果要合并太多文件,则不会尝试检测重命名,因为它担心速度很慢。很有可能在一个方向上合并超过限制,而另一个方向不合并,因此奇怪的重命名检测行为。

尝试通过

提高限额
git config merge.renameLimit 9999

并重试。