git如何检测类似文件,以进行重命名检测?


91

维基百科解释了自动重命名检测:

简而言之,给定版本N中的文件,版本N-1中具有相同名称的文件是其默认祖先。但是,当版本N-1中没有类似文件时,Git会搜索仅存在于版本N-1中且新文件非常相似的文件。

重命名检测显然可以归结为类似的文件检测。该算法在任何地方都有记录吗?知道自动检测哪些类型的转换将非常高兴。


Answers:


92

Git跟踪文件内容,而不是文件名。因此,重命名文件而不更改其内容很容易被git检测到。(Git不跟踪,但执行检测;使用git mvgit rmgit add有效地相同。)

将文件添加到存储库后,文件名在树对象中。实际文件内容将作为二进制大对象(blob)添加到存储库中。Git不会为包含相同内容的其他文件添加另一个Blob。实际上,Git不能,因为内容存储在文件系统中,哈希的前两个字符是目录名,其余的是其中的文件名。因此,检测重命名是比较散列的问题。

为了检测对重命名文件的微小更改,Git使用某些算法和阈值限制来查看这是否是重命名。例如,查看的-M标志git diff。还有一些配置值,例如merge.renameLimit(在合并期间执行重命名检测时要考虑的文件数)。

要了解git如何处理相似文件(即,将哪些文件转换视为重命名),请探索可用的配置选项和标志,如上所述。您无需考虑如何。要了解git实际上是如何完成这些任务的,请查看用于查找文本差异的算法,然后阅读git源代码。

算法仅适用于差异,合并和记录目的-它们不影响git存储它们的方式。文件内容的任何细微变化都意味着为其添加了一个新对象。在该级别上没有增量或差异发生。当然,稍后,可以将对象打包在delta存储在packfiles中的地方进行打包,但这与重命名检测无关。


57
“您无需考虑如何。” -我以为那是问题?
贝恩2014年

2

有许多算法可以检测文本之间的相似性,而版本控制系统通常已经使用这些算法来仅存储两个版本之间的差异。诸如WinMerge之类的工具足够聪明,甚至可以在行内检测差异,因此我看不出为什么不将这些算法用于此重命名检测的原因。

这是关于检测相似文本的算法的讨论。其中某些算法可能针对自然语言进行了优化,而另一些算法可能对源代码更有效,但从本质上讲,它们非常相似。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.