我很清楚Git如何支持文件移动:由于它使用文件哈希,因此“添加”的文件很容易被检测出与“删除”的文件相同。
我的问题是关于重构的:考虑Java,包声明会更改,因此文件内容将不同。在这种情况下,Git如何确定“添加”的文件与“删除”的文件共享历史记录?它会检查“最相似的内容”,假设我只进行了一些小修改,还是采用类似的非确定性解决方案?
我很清楚Git如何支持文件移动:由于它使用文件哈希,因此“添加”的文件很容易被检测出与“删除”的文件相同。
我的问题是关于重构的:考虑Java,包声明会更改,因此文件内容将不同。在这种情况下,Git如何确定“添加”的文件与“删除”的文件共享历史记录?它会检查“最相似的内容”,假设我只进行了一些小修改,还是采用类似的非确定性解决方案?
如Git FAQ所述,它将基于一种启发式方法检测相似内容。
Git必须与许多不同的工作流程进行交互,例如,某些更改可能来自补丁,其中重命名信息可能无法使用。依赖显式重命名跟踪会使得不可能合并两个树,除了一个是作为补丁(创建/删除),另一个使用其他启发式方法完成。
另外,跟踪重命名实际上只是跟踪内容在树中移动的特殊情况。在某些情况下,您可能更感兴趣的是查询何时添加或将函数移动到不同的文件中。通过仅依赖在需要时重新创建此信息的能力,Git旨在提供更灵活的跟踪树如何变化的方式。
但这并不意味着Git不支持重命名。
Git中的差异机制支持自动检测重命名,这由"-M
"开关打开,适用于git-diff-*
系列命令。
重命名检测机制被git-log(1)和git-whatchanged(1)使用,因此,例如,"git log -M
"将给出具有重命名信息的提交历史记录。
Git还支持跨重命名的有限合并形式。
两个分配责任的工具git-blame(1)
和git-annotate(1)
都使用自动重命名检测代码来跟踪重命名。
git log
会提供关于该启发式的一些详细信息:
-B[<n>][/<m>]
-M[<n>]
--follow
。如果指定了n,则它是相似性索引的阈值(即添加/删除与文件大小相比的量)。例如,-M90%表示git应该将删除/添加对视为重命名,如果文件的超过90%没有更改。
其他参考资料:
git status
现在应该显示您移动/重命名文件时的重命名(而不是删除/添加文件)。git log --follow
(参考 https://dev59.com/4XE95IYBdhLWcg3wbtXO)或是 git blame -C
)。但是这个功能不会在 Git 托管服务器端被执行(GitHub:https://dev59.com/Cm035IYBdhLWcg3wErvM#5647721)(或是 BitBucket:https://bitbucket.org/site/master/issues/589/file-history-should-follow-copies-and)。 - VonC