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.