Skip to content

Commit 982681a

Browse files
phillipwoodgitster
authored andcommitted
rebase --apply: set ORIG_HEAD correctly
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. Signed-off-by: Phillip Wood <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f517a11 commit 982681a

File tree

4 files changed

+32
-1
lines changed

4 files changed

+32
-1
lines changed

builtin/rebase.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
20792079
strbuf_addf(&msg, "%s: checkout %s",
20802080
getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
20812081
ropts.oid = &options.onto->object.oid;
2082+
ropts.orig_head = &options.orig_head,
20822083
ropts.flags = RESET_HEAD_DETACH | RESET_ORIG_HEAD |
20832084
RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
20842085
ropts.head_msg = msg.buf;

reset.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static int update_refs(const struct reset_head_opts *opts,
1414
unsigned detach_head = opts->flags & RESET_HEAD_DETACH;
1515
unsigned run_hook = opts->flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
1616
unsigned update_orig_head = opts->flags & RESET_ORIG_HEAD;
17+
const struct object_id *orig_head = opts->orig_head;
1718
const char *switch_to_branch = opts->branch;
1819
const char *reflog_branch = opts->branch_msg;
1920
const char *reflog_head = opts->head_msg;
@@ -43,7 +44,8 @@ static int update_refs(const struct reset_head_opts *opts,
4344
strbuf_addstr(&msg, "updating ORIG_HEAD");
4445
reflog_orig_head = msg.buf;
4546
}
46-
update_ref(reflog_orig_head, "ORIG_HEAD", orig,
47+
update_ref(reflog_orig_head, "ORIG_HEAD",
48+
orig_head ? orig_head : orig,
4749
old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
4850
} else if (old_orig)
4951
delete_ref(NULL, "ORIG_HEAD", old_orig, 0);

reset.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
struct reset_head_opts {
1616
/* The oid of the commit to checkout/reset to. Defaults to HEAD */
1717
const struct object_id *oid;
18+
/* Optional commit when setting ORIG_HEAD. Defaults to HEAD */
19+
const struct object_id *orig_head;
1820
/* Optional branch to switch to */
1921
const char *branch;
2022
/* Flags defined above */

t/t3418-rebase-continue.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,30 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas
323323
test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec
324324
'
325325

326+
test_orig_head_helper() {
327+
test_when_finished 'git rebase --abort &&
328+
git checkout topic &&
329+
git reset --hard commit-new-file-F2-on-topic-branch' &&
330+
git update-ref -d ORIG_HEAD &&
331+
test_must_fail git rebase "$@" &&
332+
test_cmp_rev ORIG_HEAD commit-new-file-F2-on-topic-branch
333+
}
334+
335+
test_orig_head() {
336+
type=$1
337+
test_expect_success "rebase $type sets ORIG_HEAD correctly" '
338+
git checkout topic &&
339+
git reset --hard commit-new-file-F2-on-topic-branch &&
340+
test_orig_head_helper $type main
341+
'
342+
343+
test_expect_success "rebase $type <upstream> <branch> sets ORIG_HEAD correctly" '
344+
git checkout main &&
345+
test_orig_head_helper $type main topic
346+
'
347+
}
348+
349+
test_orig_head --apply
350+
test_orig_head --merge
351+
326352
test_done

0 commit comments

Comments
 (0)