Git: capitalization of file names and name conflicts

File and directory names are case sensitive in Git, but not on a typical standard file system on Windows. This can create a tricky situation if two files have names that differ only in their capitalization in Git. The most obvious symptom can be observed when you check them out on Windows: Git will write them at the same location. More precisely, Git will overwrite the first one with the second one. If they have different contents, Git will think that the first file is modified, and report this in “git status”. “git checkout” and “git reset” won’t help. The state will always stay “modified”.

How to fix conflicts

In most cases, this situation is not wanted, e.g. the 2 files in Git should actually be one, and the duplication is unintentional. It’s easy to fix the conflict on the command line (with Git bash for instance).

git rm --cached myfile.txt
git rm --cached MYFILE.TXT

Now put the version you want in “MyFile.txt”, or whatever name you want, and commit it:

git add MyFile.txt
git commit

How to find conflicts

Here is a quick and dirty way to find conflicting files:

git ls-files | tr 'A-Z' 'a-z' | sort | uniq -d | xargs -r git ls-files

It reports conflicts with the following format:

 myfile.txt
 MYFILE.TXT
 x.txt
 X.TXT

To find directories with conflicting names, use:

git ls-files | sed -E 's/\/[^/]+$//' |  sort | uniq | tr 'A-Z' 'a-z' | sort | uniq -d

It will report each conflict with a single name (all lower case), but it should be easy to find the culprits with “git ls-tree”.

There is an alternate method for files. It’s slower, but cleaner and more reliable:

git ls-files . | xargs -n 1 git ls-files  | sort | uniq -d

It supports blanks in file names and special chars, and will find conflicts caused by ANY file system limitations, not only the capitalization (I am thinking charset issues…).
It’s quite slow however, because it starts a Git process for every file in the repository. You may want to disable your virus scanner before starting (4x speed up in my case).

Other methods, like working with the inodes, are not reliable on Windows, they report false positives.

How to create conflicts

As a bonus, here are a few way to create this situation:

  • create commits in an environment where file names are case-sensitive, for instance Linux, and check them out on Windows
  • from a commit containing myfile.txt, merge from a commit containing MYFILE.TXT
  • same thing with cherry pick

There are probably other ways, let me know if you find any.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s