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 <gitster@pobox.com>
Junio C Hamano committed
Apr 17, 2012 at 12:22 UTC
e78cbf8cbb61edfbdef5d33262f9b8cf02a3afca
4 files changed
+43
-28
builtin/merge.c
+40
-25
@@ -938,31 +938,22 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
938
}
939
940
static int finish_automerge(struct commit *head,
941
+ int head_subsumed,
942
struct commit_list *common,
943
struct commit_list *remoteheads,
944
unsigned char *result_tree,
945
const char *wt_strategy)
946
{
946
- struct commit_list *parents = NULL, *j;
947
+ struct commit_list *parents = NULL;
948
struct strbuf buf = STRBUF_INIT;
949
unsigned char result_commit[20];
950
951
free_commit_list(common);
951
- if (allow_fast_forward) {
952
- parents = remoteheads;
952
+ parents = remoteheads;
953
+ if (!head_subsumed || !allow_fast_forward)
954
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
- }
955
strbuf_addch(&merge_msg, '\n');
956
prepare_to_commit(remoteheads);
965
- free_commit_list(remoteheads);
957
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
958
NULL, sign_commit))
959
die(_("failed to write commit object"));
@@ -1137,12 +1128,16 @@ static int default_edit_option(void)
1128
st_stdin.st_mode == st_stdout.st_mode);
1129
}
1130
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)
1134
{
1135
int i;
1143
- struct commit_list *remoteheads = NULL;
1136
+ struct commit_list *remoteheads = NULL, *parents, *next;
1137
struct commit_list **remotes = &remoteheads;
1138
1139
+ if (head_commit)
1140
+ remotes = &commit_list_insert(head_commit, remotes)->next;
1141
for (i = 0; i < argc; i++) {
1142
struct commit *commit = get_merge_parent(argv[i]);
1143
if (!commit)
@@ -1150,6 +1145,20 @@ static struct commit_list *collect_parents(int argc, const char **argv)
1145
remotes = &commit_list_insert(commit, remotes)->next;
1146
}
1147
*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
+ }
1162
return remoteheads;
1163
}
1164
@@ -1161,7 +1170,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1170
struct commit *head_commit;
1171
struct strbuf buf = STRBUF_INIT;
1172
const char *head_arg;
1164
- int flag, i, ret = 0;
1173
+ int flag, i, ret = 0, head_subsumed;
1174
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
1175
struct commit_list *common = NULL;
1176
const char *best_strategy = NULL, *wt_strategy = NULL;
@@ -1270,7 +1279,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1279
head_arg = argv[1];
1280
argv += 2;
1281
argc -= 2;
1273
- remoteheads = collect_parents(argc, argv);
1282
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1283
} else if (!head_commit) {
1284
struct commit *remote_head;
1285
/*
@@ -1286,7 +1295,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1295
if (!allow_fast_forward)
1296
die(_("Non-fast-forward commit does not make sense into "
1297
"an empty head"));
1289
- remoteheads = collect_parents(argc, argv);
1298
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1299
remote_head = remoteheads->item;
1300
if (!remote_head)
1301
die(_("%s - not something we can merge"), argv[0]);
@@ -1305,7 +1314,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1314
* the standard merge summary message to be appended
1315
* to the given message.
1316
*/
1308
- remoteheads = collect_parents(argc, argv);
1317
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1318
for (p = remoteheads; p; p = p->next)
1319
merge_name(merge_remote_util(p->item)->name, &merge_names);
1320
@@ -1351,7 +1360,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1360
option_edit = 0;
1361
1362
if (!use_strategies) {
1354
- if (!remoteheads->next)
1363
+ if (!remoteheads)
1364
+ ; /* already up-to-date */
1365
+ else if (!remoteheads->next)
1366
add_strategies(pull_twohead, DEFAULT_TWOHEAD);
1367
else
1368
add_strategies(pull_octopus, DEFAULT_OCTOPUS);
@@ -1364,7 +1375,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1375
allow_trivial = 0;
1376
}
1377
1367
- if (!remoteheads->next)
1378
+ if (!remoteheads)
1379
+ ; /* already up-to-date */
1380
+ else if (!remoteheads->next)
1381
common = get_merge_bases(head_commit, remoteheads->item, 1);
1382
else {
1383
struct commit_list *list = remoteheads;
@@ -1376,10 +1389,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1389
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
1390
NULL, 0, DIE_ON_ERR);
1391
1379
- if (!common)
1392
+ if (remoteheads && !common)
1393
; /* 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)) {
1397
/*
1398
* If head can reach all the merge then we are up to date.
1399
* 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)
1567
* auto resolved the merge cleanly.
1568
*/
1569
if (automerge_was_ok) {
1556
- ret = finish_automerge(head_commit, common, remoteheads,
1570
+ ret = finish_automerge(head_commit, head_subsumed,
1571
+ common, remoteheads,
1572
result_tree, wt_strategy);
1573
goto done;
1574
}
t/t6028-merge-up-to-date.sh
+1
-1
@@ -79,7 +79,7 @@ test_expect_success 'merge -s subtree up-to-date' '
79
80
'
81
82
-test_expect_failure 'merge fast-forward octopus' '
82
+test_expect_success 'merge fast-forward octopus' '
83
84
git reset --hard c0 &&
85
test_tick &&
t/t7602-merge-octopus-many.sh
+1
-1
@@ -76,7 +76,7 @@ Merge made by the 'recursive' strategy.
76
create mode 100644 c5.c
77
EOF
78
79
-test_expect_failure 'merge reduces irrelevant remote heads' '
79
+test_expect_success 'merge reduces irrelevant remote heads' '
80
GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual &&
81
test_cmp expected actual
82
'
t/t7603-merge-reduce-heads.sh
+1
-1
@@ -119,7 +119,7 @@ test_expect_success 'fast-forward to redundant refs' '
119
git merge c4 c5
120
'
121
122
-test_expect_failure 'verify merge result' '
122
+test_expect_success 'verify merge result' '
123
test $(git rev-parse HEAD) = $(git rev-parse c5)
124
'
125