Skip to content

Commit e78cbf8

Browse files
committed
builtin/merge.c: reduce parents early
Instead of waiting until we record the parents of resulting merge, reduce redundant parents (including our HEAD) immediately after reading them. The change to t7602 illustrates the essence of the effect of this change. The octopus merge strategy used to be fed with redundant commits only to discard them as "up-to-date", but we no longer feed such redundant commits to it and the affected test degenerates to a regular two-head merge. And obviously the known-to-be-broken test in t6028 is now fixed. Signed-off-by: Junio C Hamano <[email protected]>
1 parent b5d887f commit e78cbf8

File tree

4 files changed

+43
-28
lines changed

4 files changed

+43
-28
lines changed

builtin/merge.c

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -938,31 +938,22 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
938938
}
939939

940940
static int finish_automerge(struct commit *head,
941+
int head_subsumed,
941942
struct commit_list *common,
942943
struct commit_list *remoteheads,
943944
unsigned char *result_tree,
944945
const char *wt_strategy)
945946
{
946-
struct commit_list *parents = NULL, *j;
947+
struct commit_list *parents = NULL;
947948
struct strbuf buf = STRBUF_INIT;
948949
unsigned char result_commit[20];
949950

950951
free_commit_list(common);
951-
if (allow_fast_forward) {
952-
parents = remoteheads;
952+
parents = remoteheads;
953+
if (!head_subsumed || !allow_fast_forward)
953954
commit_list_insert(head, &parents);
954-
parents = reduce_heads(parents);
955-
} else {
956-
struct commit_list **pptr = &parents;
957-
958-
pptr = &commit_list_insert(head,
959-
pptr)->next;
960-
for (j = remoteheads; j; j = j->next)
961-
pptr = &commit_list_insert(j->item, pptr)->next;
962-
}
963955
strbuf_addch(&merge_msg, '\n');
964956
prepare_to_commit(remoteheads);
965-
free_commit_list(remoteheads);
966957
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
967958
NULL, sign_commit))
968959
die(_("failed to write commit object"));
@@ -1137,19 +1128,37 @@ static int default_edit_option(void)
11371128
st_stdin.st_mode == st_stdout.st_mode);
11381129
}
11391130

1140-
static struct commit_list *collect_parents(int argc, const char **argv)
1131+
static struct commit_list *collect_parents(struct commit *head_commit,
1132+
int *head_subsumed,
1133+
int argc, const char **argv)
11411134
{
11421135
int i;
1143-
struct commit_list *remoteheads = NULL;
1136+
struct commit_list *remoteheads = NULL, *parents, *next;
11441137
struct commit_list **remotes = &remoteheads;
11451138

1139+
if (head_commit)
1140+
remotes = &commit_list_insert(head_commit, remotes)->next;
11461141
for (i = 0; i < argc; i++) {
11471142
struct commit *commit = get_merge_parent(argv[i]);
11481143
if (!commit)
11491144
die(_("%s - not something we can merge"), argv[i]);
11501145
remotes = &commit_list_insert(commit, remotes)->next;
11511146
}
11521147
*remotes = NULL;
1148+
1149+
parents = reduce_heads(remoteheads);
1150+
1151+
*head_subsumed = 1; /* we will flip this to 0 when we find it */
1152+
for (remoteheads = NULL, remotes = &remoteheads;
1153+
parents;
1154+
parents = next) {
1155+
struct commit *commit = parents->item;
1156+
next = parents->next;
1157+
if (commit == head_commit)
1158+
*head_subsumed = 0;
1159+
else
1160+
remotes = &commit_list_insert(commit, remotes)->next;
1161+
}
11531162
return remoteheads;
11541163
}
11551164

@@ -1161,7 +1170,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
11611170
struct commit *head_commit;
11621171
struct strbuf buf = STRBUF_INIT;
11631172
const char *head_arg;
1164-
int flag, i, ret = 0;
1173+
int flag, i, ret = 0, head_subsumed;
11651174
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
11661175
struct commit_list *common = NULL;
11671176
const char *best_strategy = NULL, *wt_strategy = NULL;
@@ -1270,7 +1279,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
12701279
head_arg = argv[1];
12711280
argv += 2;
12721281
argc -= 2;
1273-
remoteheads = collect_parents(argc, argv);
1282+
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
12741283
} else if (!head_commit) {
12751284
struct commit *remote_head;
12761285
/*
@@ -1286,7 +1295,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
12861295
if (!allow_fast_forward)
12871296
die(_("Non-fast-forward commit does not make sense into "
12881297
"an empty head"));
1289-
remoteheads = collect_parents(argc, argv);
1298+
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
12901299
remote_head = remoteheads->item;
12911300
if (!remote_head)
12921301
die(_("%s - not something we can merge"), argv[0]);
@@ -1305,7 +1314,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13051314
* the standard merge summary message to be appended
13061315
* to the given message.
13071316
*/
1308-
remoteheads = collect_parents(argc, argv);
1317+
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
13091318
for (p = remoteheads; p; p = p->next)
13101319
merge_name(merge_remote_util(p->item)->name, &merge_names);
13111320

@@ -1351,7 +1360,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13511360
option_edit = 0;
13521361

13531362
if (!use_strategies) {
1354-
if (!remoteheads->next)
1363+
if (!remoteheads)
1364+
; /* already up-to-date */
1365+
else if (!remoteheads->next)
13551366
add_strategies(pull_twohead, DEFAULT_TWOHEAD);
13561367
else
13571368
add_strategies(pull_octopus, DEFAULT_OCTOPUS);
@@ -1364,7 +1375,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13641375
allow_trivial = 0;
13651376
}
13661377

1367-
if (!remoteheads->next)
1378+
if (!remoteheads)
1379+
; /* already up-to-date */
1380+
else if (!remoteheads->next)
13681381
common = get_merge_bases(head_commit, remoteheads->item, 1);
13691382
else {
13701383
struct commit_list *list = remoteheads;
@@ -1376,10 +1389,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
13761389
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
13771390
NULL, 0, DIE_ON_ERR);
13781391

1379-
if (!common)
1392+
if (remoteheads && !common)
13801393
; /* No common ancestors found. We need a real merge. */
1381-
else if (!remoteheads->next && !common->next &&
1382-
common->item == remoteheads->item) {
1394+
else if (!remoteheads ||
1395+
(!remoteheads->next && !common->next &&
1396+
common->item == remoteheads->item)) {
13831397
/*
13841398
* If head can reach all the merge then we are up to date.
13851399
* but first the most common case of merging one remote.
@@ -1553,7 +1567,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
15531567
* auto resolved the merge cleanly.
15541568
*/
15551569
if (automerge_was_ok) {
1556-
ret = finish_automerge(head_commit, common, remoteheads,
1570+
ret = finish_automerge(head_commit, head_subsumed,
1571+
common, remoteheads,
15571572
result_tree, wt_strategy);
15581573
goto done;
15591574
}

t/t6028-merge-up-to-date.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ test_expect_success 'merge -s subtree up-to-date' '
7979
8080
'
8181

82-
test_expect_failure 'merge fast-forward octopus' '
82+
test_expect_success 'merge fast-forward octopus' '
8383
8484
git reset --hard c0 &&
8585
test_tick &&

t/t7602-merge-octopus-many.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Merge made by the 'recursive' strategy.
7676
create mode 100644 c5.c
7777
EOF
7878

79-
test_expect_failure 'merge reduces irrelevant remote heads' '
79+
test_expect_success 'merge reduces irrelevant remote heads' '
8080
GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual &&
8181
test_cmp expected actual
8282
'

t/t7603-merge-reduce-heads.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ test_expect_success 'fast-forward to redundant refs' '
119119
git merge c4 c5
120120
'
121121

122-
test_expect_failure 'verify merge result' '
122+
test_expect_success 'verify merge result' '
123123
test $(git rev-parse HEAD) = $(git rev-parse c5)
124124
'
125125

0 commit comments

Comments
 (0)