Skip to content

Commit e4cdfe8

Browse files
newrengitster
authored andcommitted
merge: abort if index does not match HEAD for trivial merges
As noted in the last commit and the links therein (especially commit 9822175 ("Ensure index matches head before invoking merge machinery, round N", 2019-08-17), we have had a very long history of problems with failing to enforce the requirement that index matches HEAD when starting a merge. The "trivial merge" logic in builtin/merge.c is yet another such case we previously missed. Add a check for it to ensure it aborts if the index does not match HEAD, and add a testcase where this fix is needed. Note that the fix here would also incidentally be an alternative fix for the testcase added in the last patch, but the fix in the last patch is still needed when multiple merge strategies are in use, so tweak the testcase from the previous commit so that it continues to exercise the codepath added in the last commit. Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 24ba8b7 commit e4cdfe8

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

builtin/merge.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,21 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
15991599
*/
16001600
refresh_cache(REFRESH_QUIET);
16011601
if (allow_trivial && fast_forward != FF_ONLY) {
1602+
/*
1603+
* Must first ensure that index matches HEAD before
1604+
* attempting a trivial merge.
1605+
*/
1606+
struct tree *head_tree = get_commit_tree(head_commit);
1607+
struct strbuf sb = STRBUF_INIT;
1608+
1609+
if (repo_index_has_changes(the_repository, head_tree,
1610+
&sb)) {
1611+
error(_("Your local changes to the following files would be overwritten by merge:\n %s"),
1612+
sb.buf);
1613+
strbuf_release(&sb);
1614+
return 2;
1615+
}
1616+
16021617
/* See if it is really trivial. */
16031618
git_committer_info(IDENT_STRICT);
16041619
printf(_("Trying really trivial in-index merge...\n"));

t/t6424-merge-unrelated-index-changes.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,34 @@ test_expect_success 'resolve, non-trivial' '
114114
test_path_is_missing .git/MERGE_HEAD
115115
'
116116

117+
test_expect_success 'resolve, trivial, related file removed' '
118+
git reset --hard &&
119+
git checkout B^0 &&
120+
121+
git rm a &&
122+
test_path_is_missing a &&
123+
124+
test_must_fail git merge -s resolve C^0 &&
125+
126+
test_path_is_missing a &&
127+
test_path_is_missing .git/MERGE_HEAD
128+
'
129+
117130
test_expect_success 'resolve, non-trivial, related file removed' '
118131
git reset --hard &&
119132
git checkout B^0 &&
120133
121134
git rm a &&
122135
test_path_is_missing a &&
123136
124-
test_must_fail git merge -s resolve D^0 &&
137+
# We also ask for recursive in order to turn off the "allow_trivial"
138+
# setting in builtin/merge.c, and ensure that resolve really does
139+
# correctly fail the merge (I guess this also tests that recursive
140+
# correctly fails the merge, but the main thing we are attempting
141+
# to test here is resolve and are just using the side effect of
142+
# adding recursive to ensure that resolve is actually tested rather
143+
# than the trivial merge codepath)
144+
test_must_fail git merge -s resolve -s recursive D^0 &&
125145
126146
test_path_is_missing a &&
127147
test_path_is_missing .git/MERGE_HEAD

0 commit comments

Comments
 (0)