Message ID | e8884efcc83960fc0ea5d5aee72bb9839b4be397.1633082702.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | rebase: reset_head() related fixes and improvements | expand |
"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > From: Phillip Wood <phillip.wood@dunelm.org.uk> > > At the start of a rebase ORIG_HEAD is updated to 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. All correct. It is somewhat surprising that this wasn't caught and reported as an issue for this long X-<. > + const struct object_id *orig_head; > /* Optional branch to switch to */ > const char *branch; > /* Flags defined above */ > diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh > index 738fbae9b29..be63456c5b9 100755 > --- a/t/t3418-rebase-continue.sh > +++ b/t/t3418-rebase-continue.sh > @@ -323,4 +323,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() { Need SP before "()" in addition to after it. Ditto for the other one. > + 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
diff --git a/builtin/rebase.c b/builtin/rebase.c index c40a8b843f4..c36a8a10e9b 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -2074,6 +2074,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 2c32600234d..82bcf2dcb8b 100644 --- a/reset.c +++ b/reset.c @@ -14,6 +14,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", orig, + update_ref(reflog_orig_head, "ORIG_HEAD", + orig_head ? orig_head : orig, 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 c0f4e99a3be..91a868c5ba8 100644 --- a/reset.h +++ b/reset.h @@ -15,6 +15,8 @@ struct reset_head_opts { /* The oid of the commit to checkout/reset to. Defaults to HEAD */ const struct object_id *oid; + /* Optional commit when setting ORIG_HEAD. Defaults to HEAD */ + const struct object_id *orig_head; /* Optional branch to switch to */ const char *branch; /* Flags defined above */ diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 738fbae9b29..be63456c5b9 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -323,4 +323,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