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

11,548

Solution 1

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)))

Solution 2

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.

Share:
11,548

Related videos on Youtube

James World
Author by

James World

I am an independent consultant working on a contract-only basis, I am currently fully engaged. I am a polyglot programmer, although most of my professional programming experience is in C#, which I both learned and taught over nearly a decade at Microsoft, where I also ran the performance and scalability labs for 3 years. I am full-stack developer, equally comfortable working on front and back-end systems. I have a passion for software development. This is backed by a breadth and depth of professional experience spanning over 20 years. I have worked predominantly for blue chip companies in the financial sector on Microsoft platforms. I am a regular speaker at .NET user groups and contributor on Stack Overflow where I am the #1 contributor on the Reactive Extensions tag (system.reactive). I am a passionate advocate of agile patterns and practices. I enjoy presenting to and mentoring others on what I have learned (and am still learning) about software theory, technology and disciplines.

Updated on June 04, 2022

Comments

  • James World
    James World almost 2 years

    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

    I can clearly see that this file exists on the file system, and other files in the same folder can be successfully blamed - so what is going on?

    I'm posting this question and answer as it had me stumped for a while today, and I couldn't find a single answer that hit all of the solution.

  • Fuhrmanator
    Fuhrmanator almost 4 years
    I'm eager to try this answer, except I don't know what file (directory) has been renamed. I'm getting fatal: no such path 'HEAD' in HEAD, trying to use the script at stackoverflow.com/a/13687302/1168342