summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/merge.c65
-rwxr-xr-xt/t6028-merge-up-to-date.sh2
-rwxr-xr-xt/t7602-merge-octopus-many.sh2
-rwxr-xr-xt/t7603-merge-reduce-heads.sh2
4 files changed, 43 insertions, 28 deletions
diff --git a/builtin/merge.c b/builtin/merge.c
index 2cef2f6..20aeca0 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -938,31 +938,22 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
}
static int finish_automerge(struct commit *head,
+ int head_subsumed,
struct commit_list *common,
struct commit_list *remoteheads,
unsigned char *result_tree,
const char *wt_strategy)
{
- struct commit_list *parents = NULL, *j;
+ struct commit_list *parents = NULL;
struct strbuf buf = STRBUF_INIT;
unsigned char result_commit[20];
free_commit_list(common);
- if (allow_fast_forward) {
- parents = remoteheads;
+ parents = remoteheads;
+ if (!head_subsumed || !allow_fast_forward)
commit_list_insert(head, &parents);
- parents = reduce_heads(parents);
- } else {
- struct commit_list **pptr = &parents;
-
- pptr = &commit_list_insert(head,
- pptr)->next;
- for (j = remoteheads; j; j = j->next)
- pptr = &commit_list_insert(j->item, pptr)->next;
- }
strbuf_addch(&merge_msg, '\n');
prepare_to_commit(remoteheads);
- free_commit_list(remoteheads);
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
NULL, sign_commit))
die(_("failed to write commit object"));
@@ -1137,12 +1128,16 @@ static int default_edit_option(void)
st_stdin.st_mode == st_stdout.st_mode);
}
-static struct commit_list *collect_parents(int argc, const char **argv)
+static struct commit_list *collect_parents(struct commit *head_commit,
+ int *head_subsumed,
+ int argc, const char **argv)
{
int i;
- struct commit_list *remoteheads = NULL;
+ struct commit_list *remoteheads = NULL, *parents, *next;
struct commit_list **remotes = &remoteheads;
+ if (head_commit)
+ remotes = &commit_list_insert(head_commit, remotes)->next;
for (i = 0; i < argc; i++) {
struct commit *commit = get_merge_parent(argv[i]);
if (!commit)
@@ -1150,6 +1145,20 @@ static struct commit_list *collect_parents(int argc, const char **argv)
remotes = &commit_list_insert(commit, remotes)->next;
}
*remotes = NULL;
+
+ parents = reduce_heads(remoteheads);
+
+ *head_subsumed = 1; /* we will flip this to 0 when we find it */
+ for (remoteheads = NULL, remotes = &remoteheads;
+ parents;
+ parents = next) {
+ struct commit *commit = parents->item;
+ next = parents->next;
+ if (commit == head_commit)
+ *head_subsumed = 0;
+ else
+ remotes = &commit_list_insert(commit, remotes)->next;
+ }
return remoteheads;
}
@@ -1161,7 +1170,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct commit *head_commit;
struct strbuf buf = STRBUF_INIT;
const char *head_arg;
- int flag, i, ret = 0;
+ int flag, i, ret = 0, head_subsumed;
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
struct commit_list *common = NULL;
const char *best_strategy = NULL, *wt_strategy = NULL;
@@ -1270,7 +1279,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
head_arg = argv[1];
argv += 2;
argc -= 2;
- remoteheads = collect_parents(argc, argv);
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
} else if (!head_commit) {
struct commit *remote_head;
/*
@@ -1286,7 +1295,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!allow_fast_forward)
die(_("Non-fast-forward commit does not make sense into "
"an empty head"));
- remoteheads = collect_parents(argc, argv);
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
remote_head = remoteheads->item;
if (!remote_head)
die(_("%s - not something we can merge"), argv[0]);
@@ -1305,7 +1314,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* the standard merge summary message to be appended
* to the given message.
*/
- remoteheads = collect_parents(argc, argv);
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
for (p = remoteheads; p; p = p->next)
merge_name(merge_remote_util(p->item)->name, &merge_names);
@@ -1351,7 +1360,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
option_edit = 0;
if (!use_strategies) {
- if (!remoteheads->next)
+ if (!remoteheads)
+ ; /* already up-to-date */
+ else if (!remoteheads->next)
add_strategies(pull_twohead, DEFAULT_TWOHEAD);
else
add_strategies(pull_octopus, DEFAULT_OCTOPUS);
@@ -1364,7 +1375,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
allow_trivial = 0;
}
- if (!remoteheads->next)
+ if (!remoteheads)
+ ; /* already up-to-date */
+ else if (!remoteheads->next)
common = get_merge_bases(head_commit, remoteheads->item, 1);
else {
struct commit_list *list = remoteheads;
@@ -1376,10 +1389,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
NULL, 0, DIE_ON_ERR);
- if (!common)
+ if (remoteheads && !common)
; /* No common ancestors found. We need a real merge. */
- else if (!remoteheads->next && !common->next &&
- common->item == remoteheads->item) {
+ else if (!remoteheads ||
+ (!remoteheads->next && !common->next &&
+ common->item == remoteheads->item)) {
/*
* If head can reach all the merge then we are up to date.
* 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)
* auto resolved the merge cleanly.
*/
if (automerge_was_ok) {
- ret = finish_automerge(head_commit, common, remoteheads,
+ ret = finish_automerge(head_commit, head_subsumed,
+ common, remoteheads,
result_tree, wt_strategy);
goto done;
}
diff --git a/t/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh
index 824fca5..c518e9c 100755
--- a/t/t6028-merge-up-to-date.sh
+++ b/t/t6028-merge-up-to-date.sh
@@ -79,7 +79,7 @@ test_expect_success 'merge -s subtree up-to-date' '
'
-test_expect_failure 'merge fast-forward octopus' '
+test_expect_success 'merge fast-forward octopus' '
git reset --hard c0 &&
test_tick &&
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
index 83e917b..7117b57 100755
--- a/t/t7602-merge-octopus-many.sh
+++ b/t/t7602-merge-octopus-many.sh
@@ -76,7 +76,7 @@ Merge made by the 'recursive' strategy.
create mode 100644 c5.c
EOF
-test_expect_failure 'merge reduces irrelevant remote heads' '
+test_expect_success 'merge reduces irrelevant remote heads' '
GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual &&
test_cmp expected actual
'
diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh
index f2934e8..a3b08a6 100755
--- a/t/t7603-merge-reduce-heads.sh
+++ b/t/t7603-merge-reduce-heads.sh
@@ -119,7 +119,7 @@ test_expect_success 'fast-forward to redundant refs' '
git merge c4 c5
'
-test_expect_failure 'verify merge result' '
+test_expect_success 'verify merge result' '
test $(git rev-parse HEAD) = $(git rev-parse c5)
'