git
实际上并不跟踪重命名——它依赖于“重命名检测”算法来检测重命名,如Git FAQ中所述:
Git 必须与许多不同的工作流程进行互操作,例如某些更改可能来自补丁,其中重命名信息可能不可用。依赖显式重命名跟踪使得合并两棵完成完全相同的事情的树变得不可能,除了一棵作为补丁(创建/删除),另一棵使用其他启发式方法。
其次,跟踪重命名实际上只是跟踪内容在树中如何移动的一种特殊情况。在某些情况下,您可能对查询何时添加或移动到其他文件感兴趣。通过仅在需要时重新创建此信息的能力,Git 旨在提供一种更灵活的方式来跟踪您的树的变化情况。
但是,这并不意味着 Git 不支持重命名。Git 中的 diff 机制支持自动检测重命名,这是通过 git-diff-* 命令系列的“-M”开关打开的。重命名检测机制由 git-log(1) 和 git-whatchanged(1) 使用,例如,'git log -M' 将提供带有重命名信息的提交历史记录。Git 还支持有限形式的跨重命名合并。分配责备的两个工具 git-blame(1) 和 git-annotate(1) 都使用自动重命名检测代码来跟踪重命名。
作为一个非常特殊的情况,'git log' 版本 1.5.3 及更高版本具有'--follow' 选项,允许您在给定单个路径时跟随重命名。
因此,如果你重构并重命名了一个文件,它与旧文件的相似度将非常小,结果status
或log
可能表明该文件被删除然后添加。
即使通过重构,一些选项也可能有助于检测重命名:
-M<n>
检测重命名。如果指定了n,它是相似性指数的阈值(即添加/删除量与文件大小相比)。例如,-M90% 表示如果 90% 以上的文件没有更改,git 应该将删除/添加对视为重命名。
-w
忽略空格数量的变化。这将忽略行尾的空格,并认为一个或多个空格字符的所有其他序列是等效的。
-B<n>
将完整的重写更改分解为一对删除和创建。
-B
很有用,因为它可以允许将文件视为重命名源,即使它们已被更改;例如,如果您将 90% 移至foo.c
,bar.c
但将某些功能留在foo.c
.