git 归咎于 windows 报告 "fatal: no such path <path> in HEAD"

git blame on windows reports "fatal: no such path <path> in HEAD"

当我 运行 git 责怪文件夹中的文件时,例如:

git blame Foo/FileA.txt

它returns

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 开关来执行 "what-if" 干 运行, 所以你可以检查你的重命名是否正确):

git ls-files foo | % { (& git mv $_ $('F' + $_.Substring(1))) }

上面使用 git ls-files 获取问题 "foo" 文件夹中的文件列表,将其通过管道传输到 "ForEach" (% 是它的快捷方式)然后为提供原始名称 ($_) 和 'F' 的新名称以及其余文件名 ('F' + $_.Substring(1)))[=29= 的每个文件执行 git mv ]

另一种可能性是文件或包含目录是符号 link。您可以使用 ls -l 来验证情况是否如此。尝试将文件归咎于其原始位置。

从文件目录进入终端,然后责怪应该可以。