当我在文件夹中运行 git blame 命令时(例如:git blame Foo/FileA.txt),会返回“fatal: no such path 'Foo/FileA.txt' in HEAD”的错误信息。虽然我可以在文件系统中清晰地看到该文件的存在,且该文件夹中的其他文件可以被成功追溯,但是这个问题仍然困扰着我。因为我找不到一个可以有效解决这个问题的答案,所以我分享我的疑问和答案。
这是由于在文件系统上将父文件夹重命名为一个仅大小写不同的名称 - 并且一些文件在文件夹重命名之前的提交中被添加。下面是一个可重现的示例,可以在 Powershell 提示符下执行:
mkdir C:\RenameProblem
cd C:\RenameProblem
git init
mkdir foo
"FileA" > foo/FileA.txt
git add foo/FileA.txt
git commit -m "Add FileA"
然后在Windows资源管理器中,将目录 "foo" 重命名为 "Foo",然后在 Powershell 中继续执行:
"FileB" > Foo/FileB.txt
git add Foo/FileB.txt
git commit -m "Add FileB"
此时,git blame /Foo/FileA.txt
(因为文件夹已重命名,所以自动补全会生成此选项)将失败并显示“无此路径”错误,而git blame /Foo/FileB.txt
或者git blame /foo/FileA.txt
则会成功。
此外,调用git ls-files Foo
仅会列出FileB.txt
,而git ls-files foo
则仅会列出FileA.txt
。这在Windows上并不是一个好的状态。
在我的情况下,许多文件分别位于两个版本的文件夹名称中。
您可以通过使用git mv
重命名文件来解决这个问题:
git mv foo/FileA.txt Foo/FileA.txt
git commit -am "Rename foo to Foo"
如果你需要重命名大量的文件,你可以使用一些Powershell命令(此外,请注意git mv
命令有一个-n
选项,可以进行“预演”操作,以检查您的重命名是否正确):
git ls-files foo | % { (& git mv $_ $('F' + $_.Substring(1))) }
以上使用 git ls-files
获取问题“foo”文件夹中的文件列表,将其导入到“ForEach”(%
是该命令的快捷方式),然后对于每个文件执行git mv
,提供原始名称($_
)和新名称'F'和文件名的其余部分('F' + $_.Substring(1))
)
另一种可能是文件或包含目录是符号链接。您可以使用 ls -l
命令来验证是否是这种情况。尝试在原始位置上指向文件。
从文件目录进入终端,然后运行 blame 命令即可。