Skip to content

Commit

Permalink
merge-recursive.c: fix case-changing merge bug
Browse files Browse the repository at this point in the history
On 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.

Signed-off-by: David Turner <dturner@twitter.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
David Turner authored and Junio C Hamano committed May 7, 2014
1 parent 0bc85ab commit ae352c7
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
6 changes: 6 additions & 0 deletions merge-recursive.c
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,12 @@ static int remove_file(struct merge_options *o, int clean,
return -1;
}
if (update_working_directory) {
if (ignore_case) {
struct cache_entry *ce;
ce = cache_file_exists(path, strlen(path), ignore_case);
if (ce && ce_stage(ce) == 0)
return 0;
}
if (remove_path(path))
return -1;
}
Expand Down
53 changes: 53 additions & 0 deletions t/t6039-merge-ignorecase.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/sh

test_description='git-merge with case-changing rename on case-insensitive file system'

. ./test-lib.sh

if ! test_have_prereq CASE_INSENSITIVE_FS
then
skip_all='skipping case insensitive tests - case sensitive file system'
test_done
fi

test_expect_success 'merge with case-changing rename' '
test $(git config core.ignorecase) = true &&
>TestCase &&
git add TestCase &&
git commit -m "add TestCase" &&
git tag baseline
git checkout -b with-camel &&
>foo &&
git add foo &&
git commit -m "intervening commit" &&
git checkout master &&
git rm TestCase &&
>testcase &&
git add testcase &&
git commit -m "rename to testcase" &&
git checkout with-camel &&
git merge master -m "merge" &&
test_path_is_file testcase
'

test_expect_success 'merge with case-changing rename on both sides' '
git checkout master &&
git reset --hard baseline &&
git branch -D with-camel &&
git checkout -b with-camel &&
git mv --force TestCase testcase &&
git commit -m "recase on branch" &&
>foo &&
git add foo &&
git commit -m "intervening commit" &&
git checkout master &&
git rm TestCase &&
>testcase &&
git add testcase &&
git commit -m "rename to testcase" &&
git checkout with-camel &&
git merge master -m "merge" &&
test_path_is_file testcase
'

test_done

0 comments on commit ae352c7

Please sign in to comment.