It would be useful to make `git update` reverse parents as desired. Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- Documentation/merge-options.txt | 4 ++++ builtin/commit.c | 5 +++++ builtin/merge.c | 11 ++++++++++- t/t7600-merge.sh | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index eb0aabd396..8917ed97b2 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -149,6 +149,10 @@ ifndef::git-pull[] Note that not all merge strategies may support progress reporting. +--reverse-parents:: +--no-reverse-parents:: + Reverse the order of parents in the merge commit. + endif::git-pull[] --autostash:: diff --git a/builtin/commit.c b/builtin/commit.c index f9dd155566..931738eeaf 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1724,6 +1724,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) FILE *fp; int allow_fast_forward = 1; struct commit_list **pptr = &parents; + int reverse_parents = 0; if (!reflog_msg) reflog_msg = "commit (merge)"; @@ -1744,9 +1745,13 @@ int cmd_commit(int argc, const char **argv, const char *prefix) die_errno(_("could not read MERGE_MODE")); if (strstr(sb.buf, "no-ff")) allow_fast_forward = 0; + if (strstr(sb.buf, "reverse")) + reverse_parents = 1; } if (allow_fast_forward) reduce_heads_replace(&parents); + if (reverse_parents) + parents = reverse_commit_list(parents); } else { if (!reflog_msg) reflog_msg = is_from_cherry_pick(whence) diff --git a/builtin/merge.c b/builtin/merge.c index 1836f98f82..b9c6c43d8f 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -91,6 +91,7 @@ static int signoff; static const char *sign_commit; static int autostash; static int no_verify; +static int reverse_parents; static struct strategy all_strategy[] = { { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, @@ -306,6 +307,8 @@ static struct option builtin_merge_options[] = { OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")), OPT_BOOL(0, "signoff", &signoff, N_("add a Signed-off-by trailer")), OPT_BOOL(0, "no-verify", &no_verify, N_("bypass pre-merge-commit and commit-msg hooks")), + OPT_BOOL(0, "reverse-parents", &reverse_parents, + N_("reverse the order of parents")), OPT_END() }; @@ -913,6 +916,8 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads) pptr = commit_list_append(head, pptr); pptr = commit_list_append(remoteheads->item, pptr); prepare_to_commit(remoteheads); + if (reverse_parents) + parents = reverse_commit_list(parents); if (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents, &result_commit, NULL, sign_commit)) die(_("failed to write commit object")); @@ -937,6 +942,8 @@ static int finish_automerge(struct commit *head, parents = remoteheads; if (!head_subsumed || fast_forward == FF_NO) commit_list_insert(head, &parents); + if (reverse_parents) + parents = reverse_commit_list(parents); prepare_to_commit(remoteheads); if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, &result_commit, NULL, sign_commit)) @@ -1049,7 +1056,9 @@ static void write_merge_heads(struct commit_list *remoteheads) strbuf_reset(&buf); if (fast_forward == FF_NO) - strbuf_addstr(&buf, "no-ff"); + strbuf_addstr(&buf, "no-ff "); + if (reverse_parents) + strbuf_addstr(&buf, "reverse "); write_file_buf(git_path_merge_mode(the_repository), buf.buf, buf.len); strbuf_release(&buf); } diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 10f8956665..660d13dd51 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -563,6 +563,16 @@ test_expect_success 'merge c0 with c1 (no-ff)' ' test_debug 'git log --graph --decorate --oneline --all' +test_expect_success 'merge c0 with c1 (--reverse-parents)' ' + git reset --hard c0 && + test_tick && + git merge --no-ff --reverse-parents c1 && + verify_merge file result.1 && + verify_parents $c1 $c0 +' + +test_debug 'git log --graph --decorate --oneline --all' + test_expect_success 'merge c0 with c1 (merge.ff=false)' ' git reset --hard c0 && test_config merge.ff "false" && @@ -940,6 +950,22 @@ test_expect_success 'merge annotated/signed tag w/ tracking' ' ) ' +test_expect_success 'merge --reverse-parents --no-commit && commit' ' + git reset --hard c0 && + git merge --no-ff --reverse-parents --no-commit c1 && + EDITOR=: git commit && + verify_parents $c1 $c0 +' + +test_debug 'git log --graph --decorate --oneline --all' + +test_expect_success 'amending reverse merge commit' ' + EDITOR=: git commit --amend && + verify_parents $c1 $c0 +' + +test_debug 'git log --graph --decorate --oneline --all' + test_expect_success GPG 'merge --ff-only tag' ' git reset --hard c0 && git commit --allow-empty -m "A newer commit" && -- 2.32.0.36.g70aac2b1aa