Before Git 2.30 (Q1 2021), "git rebase -i
"(man) did not store ORIG_HEAD
correctly.
See commit 8843302, commit a2bb10d, commit f3e27a0, commit e100bea (04 Nov 2020) by Phillip Wood (phillipwood
).
(Merged by Junio C Hamano -- gitster
-- in commit c042c45, 18 Nov 2020)
rebase -i
: stop overwriting ORIG_HEAD
buffer
Reported-by: Caspar Duregger
Signed-off-by: Phillip Wood
After rebasing, ORIG_HEAD
is supposed to point to the old HEAD of the rebased branch.
The code used find_unique_abbrev()
to obtain the object name of the old HEAD and wrote to both .git/rebase-merge/orig-head (used by rebase --abort
to go back to the previous state) and to ORIG_HEAD
.
The buffer find_unique_abbrev()
gives back is volatile, unfortunately, and was overwritten after the former file is written but before ORIG_FILE
is written, leaving an incorrect object name in it.
Avoid relying on the volatile buffer of find_unique_abbrev()
, and instead supply our own buffer to keep the object name.
I think that all of the users of head_hash
should actually be using opts->orig_head
instead as passing a string rather than a struct object_id
around is a hang over from the scripted implementation.
This patch just fixes the immediate bug and adds a regression test based on Caspar's reproduction example. The users will be converted to use struct object_id
and head_hash
removed in the next few commits.
Note: from the Git mailing list:
git-rebase -i
# edit XYZ
git-reset HEAD~
git-commit -C ORIG_HEAD -a
git-rebase --continue
git-show ORIG_HEAD
ORIG_HEAD
does not point at the previous HEAD of the rebased branch.
ORIG_HEAD points to XYZ
"git reset
" will update ORIG_HEAD to the current HEAD before resetting
so here ORIG_HEAD
gets updated to point to XYZ
.
One can use the reflog to get the previous HEAD of the rebased branch after rebasing.
Immediately after the rebase, branch-name@{1}
will point
to the pre-rebase HEAD.