]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rebase --apply: set ORIG_HEAD correctly
authorPhillip Wood <phillip.wood@dunelm.org.uk>
Wed, 26 Jan 2022 13:05:48 +0000 (13:05 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Jan 2022 20:08:53 +0000 (12:08 -0800)
At the start of a rebase, ORIG_HEAD is updated to the tip of the
branch being rebased. Unfortunately reset_head() always uses the
current value of HEAD for this which is incorrect if the rebase is
started with "git rebase <upstream> <branch>" as in that case
ORIG_HEAD should be updated to <branch>. This only affects the "apply"
backend as the "merge" backend does not yet use reset_head() for the
initial checkout. Fix this by passing in orig_head when calling
reset_head() and add some regression tests.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/rebase.c
reset.c
reset.h
t/t3418-rebase-continue.sh

index b55a9cff05db2820763d2d50eed740e4d27845a4..e942c300f8c140d76802a0b719e8d7b37d58e4a1 100644 (file)
@@ -1769,6 +1769,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        strbuf_addf(&msg, "%s: checkout %s",
                    getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
        ropts.oid = &options.onto->object.oid;
+       ropts.orig_head = &options.orig_head,
        ropts.flags = RESET_HEAD_DETACH | RESET_ORIG_HEAD |
                        RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
        ropts.head_msg = msg.buf;
diff --git a/reset.c b/reset.c
index e02915c0f65fd3bd804c7f954e47eb548014f117..448cb3fd78576ed72f0415f2d3b0bdfc3b60a8a4 100644 (file)
--- a/reset.c
+++ b/reset.c
@@ -15,6 +15,7 @@ static int update_refs(const struct reset_head_opts *opts,
        unsigned detach_head = opts->flags & RESET_HEAD_DETACH;
        unsigned run_hook = opts->flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
        unsigned update_orig_head = opts->flags & RESET_ORIG_HEAD;
+       const struct object_id *orig_head = opts->orig_head;
        const char *switch_to_branch = opts->branch;
        const char *reflog_branch = opts->branch_msg;
        const char *reflog_head = opts->head_msg;
@@ -43,7 +44,8 @@ static int update_refs(const struct reset_head_opts *opts,
                                strbuf_addstr(&msg, "updating ORIG_HEAD");
                                reflog_orig_head = msg.buf;
                        }
-                       update_ref(reflog_orig_head, "ORIG_HEAD", head,
+                       update_ref(reflog_orig_head, "ORIG_HEAD",
+                                  orig_head ? orig_head : head,
                                   old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
                } else if (old_orig)
                        delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
diff --git a/reset.h b/reset.h
index 7ef7e43ea8c785405de7e4e1b804c982ebf31c3c..a28f81829d859dc3dfd3817d6449ab7eb195b0d3 100644 (file)
--- a/reset.h
+++ b/reset.h
@@ -22,6 +22,10 @@ struct reset_head_opts {
         * The commit to checkout/reset to. Defaults to HEAD.
         */
        const struct object_id *oid;
+       /*
+        * Optional value to set ORIG_HEAD. Defaults to HEAD.
+        */
+       const struct object_id *orig_head;
        /*
         * Optional branch to switch to.
         */
index 22eca73aa3e926cf58d0c723f97c1d0394021371..130e2f9b553003b9972ebe1010f17abff2d5ee05 100755 (executable)
@@ -308,4 +308,30 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas
        test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec
 '
 
+test_orig_head_helper () {
+       test_when_finished 'git rebase --abort &&
+               git checkout topic &&
+               git reset --hard commit-new-file-F2-on-topic-branch' &&
+       git update-ref -d ORIG_HEAD &&
+       test_must_fail git rebase "$@" &&
+       test_cmp_rev ORIG_HEAD commit-new-file-F2-on-topic-branch
+}
+
+test_orig_head () {
+       type=$1
+       test_expect_success "rebase $type sets ORIG_HEAD correctly" '
+               git checkout topic &&
+               git reset --hard commit-new-file-F2-on-topic-branch &&
+               test_orig_head_helper $type main
+       '
+
+       test_expect_success "rebase $type <upstream> <branch> sets ORIG_HEAD correctly" '
+               git checkout main &&
+               test_orig_head_helper $type main topic
+       '
+}
+
+test_orig_head --apply
+test_orig_head --merge
+
 test_done