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.