rebase --apply: fix reflog

move_to_original_branch() passes the message intended for the branch reflog as `orig_head_msg`. Fix this by adding a `branch_msg` member to struct reset_head_opts and add a regression test. Note that these reflog messages do not respect GIT_REFLOG_ACTION. They are not alone in that and will be fixed in a future series. The "merge" backend already has tests that check both the branch and HEAD reflogs. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Jan 26, 2022 at 13:05 UTC 7700ab087b82f71d19134141045b95063e407344
4 files changed +41 -6
builtin/rebase.c
+4 -4
@@ -570,7 +570,7 @@ static int finish_rebase(struct rebase_options *opts)
570
571 static int move_to_original_branch(struct rebase_options *opts)
572 {
573 - struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
573 + struct strbuf branch_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
574 struct reset_head_opts ropts = { 0 };
575 int ret;
576
@@ -580,17 +580,17 @@ static int move_to_original_branch(struct rebase_options *opts)
580 if (!opts->onto)
581 BUG("move_to_original_branch without onto");
582
583 - strbuf_addf(&orig_head_reflog, "rebase finished: %s onto %s",
583 + strbuf_addf(&branch_reflog, "rebase finished: %s onto %s",
584 opts->head_name, oid_to_hex(&opts->onto->object.oid));
585 strbuf_addf(&head_reflog, "rebase finished: returning to %s",
586 opts->head_name);
587 ropts.branch = opts->head_name;
588 ropts.flags = RESET_HEAD_REFS_ONLY;
589 - ropts.orig_head_msg = orig_head_reflog.buf;
589 + ropts.branch_msg = branch_reflog.buf;
590 ropts.head_msg = head_reflog.buf;
591 ret = reset_head(the_repository, &ropts);
592
593 - strbuf_release(&orig_head_reflog);
593 + strbuf_release(&branch_reflog);
594 strbuf_release(&head_reflog);
595 return ret;
596 }
reset.c
+10 -2
@@ -16,6 +16,7 @@ static int update_refs(const struct reset_head_opts *opts,
16 unsigned run_hook = opts->flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
17 unsigned update_orig_head = opts->flags & RESET_ORIG_HEAD;
18 const char *switch_to_branch = opts->branch;
19 + const char *reflog_branch = opts->branch_msg;
20 const char *reflog_head = opts->head_msg;
21 const char *reflog_orig_head = opts->orig_head_msg;
22 const char *default_reflog_action = opts->default_reflog_action;
@@ -58,8 +59,9 @@ static int update_refs(const struct reset_head_opts *opts,
59 detach_head ? REF_NO_DEREF : 0,
60 UPDATE_REFS_MSG_ON_ERR);
61 else {
61 - ret = update_ref(reflog_head, switch_to_branch, oid,
62 - NULL, 0, UPDATE_REFS_MSG_ON_ERR);
62 + ret = update_ref(reflog_branch ? reflog_branch : reflog_head,
63 + switch_to_branch, oid, NULL, 0,
64 + UPDATE_REFS_MSG_ON_ERR);
65 if (!ret)
66 ret = create_symref("HEAD", switch_to_branch,
67 reflog_head);
@@ -90,6 +92,12 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts)
92 if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
93 BUG("Not a fully qualified branch: '%s'", switch_to_branch);
94
95 + if (opts->orig_head_msg && !update_orig_head)
96 + BUG("ORIG_HEAD reflog message given without updating ORIG_HEAD");
97 +
98 + if (opts->branch_msg && !opts->branch)
99 + BUG("branch reflog message given without a branch");
100 +
101 if (!refs_only && repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
102 ret = -1;
103 goto leave_reset_head;
reset.h
+4
@@ -30,6 +30,10 @@ struct reset_head_opts {
30 * Flags defined above.
31 */
32 unsigned flags;
33 + /*
34 + * Optional reflog message for branch, defaults to head_msg.
35 + */
36 + const char *branch_msg;
37 /*
38 * Optional reflog message for HEAD, if this omitted but oid or branch
39 * are given then default_reflog_action must be given.
t/t3406-rebase-message.sh
+23
@@ -105,6 +105,29 @@ test_expect_success 'GIT_REFLOG_ACTION' '
105 test_cmp expect actual
106 '
107
108 +test_expect_success 'rebase --apply reflog' '
109 + git checkout -b reflog-apply start &&
110 + old_head_reflog="$(git log -g --format=%gs -1 HEAD)" &&
111 +
112 + git rebase --apply Y &&
113 +
114 + git log -g --format=%gs -4 HEAD >actual &&
115 + cat >expect <<-EOF &&
116 + rebase finished: returning to refs/heads/reflog-apply
117 + rebase: Z
118 + rebase: checkout Y
119 + $old_head_reflog
120 + EOF
121 + test_cmp expect actual &&
122 +
123 + git log -g --format=%gs -2 reflog-apply >actual &&
124 + cat >expect <<-EOF &&
125 + rebase finished: refs/heads/reflog-apply onto $(git rev-parse Y)
126 + branch: Created from start
127 + EOF
128 + test_cmp expect actual
129 +'
130 +
131 test_expect_success 'rebase -i onto unrelated history' '
132 git init unrelated &&
133 test_commit -C unrelated 1 &&