Reputation: 39603
I wrote this script and ran it on OSX 10.8 Mountain Lion, on the default case-insensitive HFS filesystem.
#!/bin/sh -x
# create git repo
rm -rf caps
git init caps
cd caps
# commit empty file called "file"
touch file
git add .
git commit -am "initial commit"
# create branch called "branch"
git branch branch
# rename "file" to "File"
# using --force per http://stackoverflow.com/questions/6899582
git mv --force file File
git commit -am "renamed capital"
# switch to branch, make a non-conflicting commit
git checkout branch
touch newfile
git add .
git commit -am "branch commit"
# merge master into branch, commit merge
git merge --commit --no-edit master
# but where's the renamed File?
more File
When the script was done, it failed on the last line, when it should have succeeded:
+ git merge --commit --no-edit master
Removing file
Merge made by the 'recursive' strategy.
file => File | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename file => File (100%)
+ more File
File: No such file or directory
git status showed this:
$ git status
# On branch branch
# 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: File
#
no changes added to commit (use "git add" and/or "git commit -a")
We can get the file back at that point with git checkout File
, but it's very easy at that point to accidentally commit the deletion.
We've been renaming quite a few files lately, fixing their capitalization, and this has bit our team a lot. Is there a git setting or best practice we can use to workaround this problem? (For now, we're just telling everybody to be extra extra careful.)
Upvotes: 4
Views: 513
Reputation: 1329812
That issue ("deletes file with renamed capitalization") is precisely what commit ae352c7f37ef2098e03ee86bc7fd75b210b17683 by David Turner (dturner-tw
) solves:
merge-recursive.c
: fix case-changing merge bugOn a case-insensitive filesystem, when merging, a file would be wrongly deleted from the working tree if an incoming commit had renamed it changing only its case.
When merging a rename, the file with the old name would be deleted -- but since the filesystem considers the old name to be the same as the new name, the new file would in fact be deleted.We avoid this by not deleting files that have a case-clone in the index at stage 0.
That means that, starting git 2.0.1+ (June 25th, 2014), the merge should now work.
Upvotes: 1
Reputation: 39603
This problem only occurs when rename detection fails.
http://thread.gmane.org/gmane.comp.version-control.git/235889
It just so happens that git disabled rename detection of empty files in git 1.8. https://github.com/git/git/commit/4f7cb99ada26be5d86402a6e060f3ee16a672f16
This script runs as expected on git 1.7 and git 1.8:
#!/bin/sh -x
# create git repo
git --version
rm -rf caps
git init caps
cd caps
git config --get core.ignorecase
# commit empty file called "file"
echo file > file
git add .
git commit -am "initial commit"
# create branch called "branch"
git branch branch
# rename "file" to "File"
# using --force per http://stackoverflow.com/questions/6899582
git mv --force file File
git commit -am "renamed to File"
# switch to branch, make a non-conflicting commit
git checkout branch
echo newfile > newfile
git add .
git commit -am "branch commit"
# merge master into branch, commit merge
GIT_EDITOR=true git merge --verbose --commit master
ls File
git status
But this script fails, due to a bug in git:
#!/bin/sh -x
# create git repo
git --version
rm -rf caps
git init caps
cd caps
git config --get core.ignorecase
# commit empty file called "file"
echo file > file
git add .
git commit -am "initial commit"
# create branch called "branch"
git branch branch
# rename "file" to "File"
# using --force per http://stackoverflow.com/questions/6899582
git mv --force file File
echo "completely different content" > File
git commit -am "renamed to File"
# switch to branch, make a non-conflicting commit
git checkout branch
echo newfile > newfile
git add .
git commit -am "branch commit"
# merge master into branch, commit merge
GIT_EDITOR=true git merge --verbose --commit master
ls File
git status
Upvotes: 0