维基百科解释了自动重命名检测:
简而言之,给定修订版N中的文件,修订版N-1中的同名文件是其默认祖先.但是,当修订版N-1中没有同名文件时,Git会搜索仅存在于修订版N-1中的文件,并且与新文件非常相似.
重命名检测显然归结为类似的文件检测.这个算法记录在哪里吗?很高兴知道自动检测到哪种变换.
考虑一下我们将以下命令应用于hello.txtgit 下跟踪的文件(在干净的工作副本中):
echo "hi" >> hello.txt
mv hello.txt bye.txt
git rm hello.txt
git add bye.txt
git status
Run Code Online (Sandbox Code Playgroud)
结果:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: hello.txt -> bye.txt
Run Code Online (Sandbox Code Playgroud)
因此,git 知道它是同一个文件,即使它被重命名了。我有一些模糊的记忆,git 检查 inode 以确定新文件与旧的已删除文件相同。 不过,这个和这个SO 答案表明 git 只检查文件的内容,并且不会以任何方式检查它是否是相同的 inode。(我的结论(*):如果我对文件进行更大的修改,git 将不会检测到重命名,即使 inode 仍然相同。)
因此,在我看来,很明显,我错了,git 不检查 inode(或任何其他文件系统信息),只检查内容。但后来,我发现了另一个答案,它声称
除了时间戳之外,它[即git]还记录lstat的大小、inode和其他信息,以减少误报的机会。当您执行 git-status 时,它只需对工作树中的每个文件调用 lstat 并比较元数据,以便快速确定哪些文件未更改。
我对此实际上有两个问题:
Git 确实依赖(也)依赖 inode 来检测文件是否已更改,但它不使用 inode 来检测文件重命名。