When I run git blame on a file in a folder e,g,:
git blame Foo/FileA.txt
it returns
fatal: no such path \'Foo/FileA.txt\' in HEAD
Another possibility is that the file or a containing directory are a symbolic link. You can use ls -l
to verify this is the case. Try to blame the file in its original location instead.
Entering the terminal from the file directory and then blaming it shall work.
This is due to renaming a parent folder on the file system with a new name that varies only by case - and some files were added in a commit occurring before the rename of the folder. Here is a repro, from a Powershell prompt:
mkdir C:\RenameProblem
cd C:\RenameProblem
git init
mkdir foo
"FileA" > foo/FileA.txt
git add foo/FileA.txt
git commit -m "Add FileA"
Then in windows explorer, rename directory "foo" to "Foo" and then continue in Powershell with:
"FileB" > Foo/FileB.txt
git add Foo/FileB.txt
git commit -m "Add FileB"
At this point, git blame /Foo/FileA.txt
(which tab completion will generate since the folder has renamed) will fail with the no such path error, whereas git blame /Foo/FileB.txt
or even git blame /foo/FileA.txt
will succeed.
Futhermore, a call to git ls-files Foo
will list only FileB.txt
and git ls-files foo
will list only FileA.txt
. Not a great place to be on Windows.
In my case, I had a large number of files split between the two versions of the folder name.
You can solve this by renaming the file with git mv
:
git mv foo/FileA.txt Foo/FileA.txt
git commit -am "Rename foo to Foo"
If you need to rename a lot of files, use a bit of Powershell (also, note that git mv
has a -n
switch to do a "what-if" dry run, so you can check your rename is correct):
git ls-files foo | % { (& git mv $_ $('F' + $_.Substring(1))) }
The above uses git ls-files
to get a list of files in the problem "foo" folder, pipes this into a "ForEach" (%
is the shortcut for that) and then executes git mv
for each file supplying the original name ($_
) and the new name of 'F' and the rest of the file name ('F' + $_.Substring(1))
)