我刚刚经历了一个有点痛苦的过程,在功能分支上重命名/重组和重构大型代码库。在此过程中,我进行了几次更改的增量签名,以确保git识别重命名。但是,现在我将这个功能合并到我的开发分支中,看起来Git并没有“记住”这些重命名,而是将它们视为删除/添加。设置不同的重命名阈值似乎没有帮助。
git不应该从之前的提交中知道文件被重命名/移动了吗?
修改 奇怪的是,如果我将dev合并到我的功能分支中,而不是反之亦然,git似乎会识别重命名。我最终做了这个,然后将dev重置为我的功能分支的顶部。在这种情况下,合并的方向是否重要?
答案 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时遵循重命名的选项 单一路径。
因此,如果您重构了并重命名了一个文件,那么它与旧文件的相似性将非常小,结果status
或log
可能表示该文件被删除然后添加。
一些选项可能有助于检测重命名,即使是通过重构:
-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
并重试。