Duplicated file with different case in git origin (bitbucket)
I am trying to rename files from foobar.php to FooBar.php which is quite a challenge in Git. So far I have found out that I had to set up the git config value of ignorecase
to false
(why it was set to true on Mac OS X, anyway?). I have managed to rename those files successfully in my local repository, but after I pushed it to BitBucket I've got FooBar.php
as well as foobar.php
there. How do I get rid of these duplicates? Thanks.
Solution 1:
Case-insensitive, case-preserving
The problem you likely have is that the default file system on a mac is case-insensitive but case preserving; it is not possible in that circumstance for file.php
and File.php
to exist at the same time - they are considered the same file.
This is easy to demonstrate:
$ cd /tmp
$ mkdir example
$ cd example/
$ git init
Initialized empty Git repository in /private/tmp/so/.git/
$ touch readme
$ git add readme
$ git commit -m "adding readme"
[master (root-commit) 05fdf7d] adding readme
0 files changed
create mode 100644 readme
$ mv readme x
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: readme
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# x
no changes added to commit (use "git add" and/or "git commit -a")
$ mv x README
$ git status
# On branch master
nothing to commit (working directory clean)
$ ls -l
total 0
-rw-r--r-- 1 andy wheel 0 Aug 1 19:38 README
In the above the file is now named README
yet according to git the file readme
exists and is unmodified.
Use two commits
So instead of renaming the file (which on a case-insensitive system is problematic) do it as two steps:
$ mv file.php /tmp
$ git rm file.php
$ git commit -m "deleting file"
$ git push
Make sure that the undesired file is gone from the repository. Then, move the file back to the right location and add it.
$ mv /tmp/file.php File.php
$ git add File.php
$ git commit -m "adding File"
$ git push
Solution 2:
Applied to Directories
As I was struggling with this issue on a directory level (rather than on a file level), here is the recipe applied to a folder (this was on Windows, git v2.9.2).
- Bitbucket would be showing two subfolders, say Foobar and FooBar, with different files/folders beneath them.
- On the client core.ignorecase was set to true and both file trees where merged into one under a common root, say Foobar.
- Don't set core.ignorecase to false just yet, as it will leave you suddenly with "untracked" files from the other path!
-
git mv Foobar Foobar.tmp
- You will get a set of renamed files, but also a set of deleted files and their corresponding untracked ones from the other path. -
git add .
- Stage all the deleted/untracked files.- That worked ok for me. Although these appear as deletes/additions, the history of those files is not lost (magically).
-
git commit -m"syncing Foo[Bb]ar into temp. folder"
- Commit the temp. folder. -
git mv Foobar.tmp FooBar
- Now rename from temp. to the desired name. -
git commit -m"moving FooBar into place"
- Commit the target name. -
git push
- Now Bitbucket should show a single subdirectory FooBar. -
git config [--global] core.ignorecase false
- Never stumble into that problem again.
Solution 3:
Clone/checkout into a case-sensitive file system (on Mac OS X you can just make a case-sensitive disk image to do so), and then git rm
the file with the capitalization you don't want.
As to why ignorecase
was set to true, the documentation says:
core.ignorecase
The default is false, exceptgit-clone(1)
orgit-init(1)
will probe and setcore.ignorecase
true if appropriate when the repository is created.
Since your Mac probably has a case-insensitive filesystem (it's the default), git
will have noticed that and set the flag appropriately.