git如何检测类似的文件,重命名检测?

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

简而言之,给定修订版本N中的文件,修订版N-1中具有相同名称的文件是其默认祖先。 但是,如果修订版N-1中没有类似名称的文件,则Git会search仅存在于修订版N-1中的文件,并且新文件非常相似

重命名检测显然归结为类似的文件检测。 这个algorithm是否在任何地方logging 这将是很高兴知道自动检测到什么样的转换。

Git跟踪文件内容,而不是文件名。 所以重命名一个文件而不改变它的内容很容易被git检测到。 (Git没有跟踪,但执行检测 ;使用git mvgit rmgit add实际上是相同的。)

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

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

为了理解git如何处理类似的文件(例如,哪些文件转换被视为重命名),请浏览上面提到的configuration选项和可用的标志。 你不需要考虑如何。 要理解git如何实际完成这些任务,请查看用于查找文本差异的algorithm,并阅读git源代码。

algorithm仅适用于diff,merge和log目的 – 它们不影响git如何存储它们。 文件内容的任何小的改变意味着添加一个新的对象。 在这个级别上没有delta或diff。 当然,以后,这些对象可能会打包在存储在packfiles中的三angular洲,但是这与重命名检测无关。

有许多algorithm检测文本之间的相似性,版本控制系统经常使用这些algorithm来仅存储两个版本之间的差异。 像WinMerge这样的工具足够聪明,能够检测到差异,即使在行内也是如此,所以我没有看到为什么这些algorithm不会被用于重命名检测的原因。

这里是关于检测类似文本的algorithm的讨论。 其中一些algorithm可能会针对自然语言进行优化,而另一些可能对源代码更好,但本质上它们非常相似。