1

When trying

git mv dir1/File.py dir2

I get

fatal: not under version control, source=dir1/File.py, destination=dir2/File.py

To debug I run

git ls-files | grep File.py

Luckily I had alias grep="grep -i" and the problem is clear. file.py is under version control. File.py isn't.

I'm guessing that I have once renamed file.py to File.py from the shell (on OS X this usually requires going through a third name). Git continued to treat the two files as the same, because OS X treats them as one. But git refuses to move a file unless the case also matches.

How do I systematically determine whether there are similar case sensitivity problems lurking within a git repo?

I'm using the default formatting of OS X extended (Journaled), which is not case-sensitive, and I'd like to keep it that way.

Update

I just noticed this relevant post.

Community
  • 1
  • 1
Calaf
  • 10,113
  • 15
  • 57
  • 120

1 Answers1

0

This is a bit hacky, but it should work, in Bash:

git ls-files | xargs -I{} sh -c 'ls "{}"* &>/dev/null || echo {}'

The goal is to run a command that reveals the actual case of the file.

Consider this:

$ ls
A.md

We have a single file named A.md. But then:

$ ls a.md
a.md

What? Even though the actual name is A.md, the shell matches it to a.md -- the wrong case.

Luckily, this works differently when we use globs:

$ ls a.md*
ls: a.md*: No such file or directory
$ ls A.md*
A.md

This is what we're looking for: by doing ls the-file*, we can verify if that exact name really exists or not.

For this to work, the nocaseglob option of Bash must be off:

shopt -u nocaseglob

The command at the very top runs for each file in the repository this shell:

ls "{}"* &>/dev/null || echo {}

Here, {} is the name of the file in the loop iteration, and we try to do a ls {}*, discard the output of the command, and if the command failed, we print the filename that we tried. The command fails if the file doesn't exist: for example because the case of the filename is different.

The output of the command at the top will be the list of files that are in your Git repository, but cannot be found by the same name. These are the files you need to fix.

Limitations: the command may not work well in some cases:

  • If you have multiple files with the same beginning
  • If you have files with newline in the name

Lastly, you can change the case of a file without going through a 3rd intermediary name in Finder.

If you have no changes in your working tree, then a simple way to fix the names is to remove them from the workspace and then checkout:

git ls-files | xargs -I{} sh -c 'ls "{}"* &>/dev/null || echo {}' | xargs rm
git checkout .
janos
  • 120,954
  • 29
  • 226
  • 236