Git is a case sensitive version control system. Thus, it allows you to commit files and folders that differ only in case. This is perfectly legal and something that Azure DevOps and Team Foundation Server (and, really, every Git hosting provider) have to allow and support.
You can see this by running git ls-tree HEAD
in your repository. It will show files in both the case variations.
One of two things has happened:
- Somebody has cloned your repository on a case-sensitive filesystem (like Linux) and created a directory that differs only in case, added files to it and committed them. This is reasonably unlikely.
- Much more likely is that somebody has cloned their repository onto a case-insensitive filesystem (like Windows) and disabled
core.ignorecase
. core.ignorecase
instructs Git that you are on a case-insensitive filesystem and that if you run git add FOO/file.txt
when there's a directory named foo
already in the repository, that you actually want to use the existing directory.
core.ignorecase
is not a setting that should be changed. It is not an option. It is a cached value. Git discovers your filesystem capabilities when the repository is created (case sensitivity, Unicode capabilities) and caches them so that it doesn't have to re-discover this information on every command.
This value is not intended to be changed, otherwise you risk problems like this.
To resolve this, you can stage a rename from one case to the other. For example, if you have a repository that contains a folder named foo
and another folder named FOO
. Imagine that you have two files, foo/bar
and FOO/baz
:
% git ls-files --stage
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 FOO/baz
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 foo/bar
To resolve this, decide which name you want to keep (foo
or FOO
) and rename the other. You'll need to use git mv
with the -f
flag:
% git mv -f FOO/baz foo/baz
% git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: FOO/baz -> foo/baz
You can check that in to resolve the problem.
If you have two files with the same name but that differ in case, you'll need to decide which name to keep.
% git ls-files --stage
100644 ba578e48b183662ddf9b38682cc52fb80066ce6d 0 FOO/bar
100644 5716ca5987cbf97d6bb54920bea6adde242d87e6 0 foo/bar
To remove the other file, use the --cached
flag to git rm
to prevent removing it from the disk.
% git rm --cached FOO/bar
% git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: FOO/bar