Skip to content

Commit f309e8e

Browse files
committed
merge-recursive: do not look at the index during recursive merge
When merging another branch into ours, if their tree is the same as the common ancestor's, we can declare that our tree represents the result of three-way merge. In such a case, the recursive merge backend incorrectly used to create a commit out of our index, even when the index has changes. A recent fix attempted to prevent this by adding a comparison between "our" tree and the index, but forgot that this check must be restricted only to the outermost merge. Inner merges performed by the recursive backend across merge bases are by definition made from scratch without having any local changes added to the index. The call to index_has_changes() during an inner merge is working on the index that has no relation to the merge being performed, preventing legitimate merges from getting carried out. Fix it by limiting the check to the outermost merge. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 65170c0 commit f309e8e

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

merge-recursive.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1954,7 +1954,7 @@ int merge_trees(struct merge_options *o,
19541954
if (oid_eq(&common->object.oid, &merge->object.oid)) {
19551955
struct strbuf sb = STRBUF_INIT;
19561956

1957-
if (index_has_changes(&sb)) {
1957+
if (!o->call_depth && index_has_changes(&sb)) {
19581958
err(o, _("Dirty index: cannot merge (dirty: %s)"),
19591959
sb.buf);
19601960
return 0;

t/t3030-merge-recursive.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,4 +678,54 @@ test_expect_success 'merge-recursive remembers the names of all base trees' '
678678
test_cmp expect actual
679679
'
680680

681+
test_expect_success 'merge-recursive internal merge resolves to the sameness' '
682+
git reset --hard HEAD &&
683+
684+
# We are going to create a history leading to two criss-cross
685+
# branches A and B. The common ancestor at the bottom, O0,
686+
# has two child commits O1 and O2, both of which will be merge
687+
# base between A and B, like so:
688+
#
689+
# O1---A
690+
# / \ /
691+
# O0 .
692+
# \ / \
693+
# O2---B
694+
#
695+
# The recently added "check to see if the index is different from
696+
# the tree into which something else is getting merged" check must
697+
# NOT kick in when an inner merge between O1 and O2 is made. Both
698+
# O1 and O2 happen to have the same tree as O0 in this test to
699+
# trigger the bug---whether the inner merge is made by merging O2
700+
# into O1 or O1 into O2, their common ancestor O0 and the branch
701+
# being merged have the same tree. We should not trigger the "is
702+
# the index dirty?" check in this case.
703+
704+
echo "zero" >file &&
705+
git add file &&
706+
test_tick &&
707+
git commit -m "O0" &&
708+
O0=$(git rev-parse HEAD) &&
709+
710+
test_tick &&
711+
git commit --allow-empty -m "O1" &&
712+
O1=$(git rev-parse HEAD) &&
713+
714+
git reset --hard $O0 &&
715+
test_tick &&
716+
git commit --allow-empty -m "O2" &&
717+
O2=$(git rev-parse HEAD) &&
718+
719+
test_tick &&
720+
git merge -s ours $O1 &&
721+
B=$(git rev-parse HEAD) &&
722+
723+
git reset --hard $O1 &&
724+
test_tick &&
725+
git merge -s ours $O2 &&
726+
A=$(git rev-parse HEAD) &&
727+
728+
git merge $B
729+
'
730+
681731
test_done

0 commit comments

Comments
 (0)