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