How to abort an interactive rebase if --abort doesn't work?

164.7k views Asked by At

I've got myself into a muddle via an interactive rebase, and I now wish to abort it. (i.e. go back to the point before I was dropped into interactive rebase mode, in my case via git pull --rebase.) The way to do this seems to be via git rebase --abort, but this doesn't work:

$ git rebase --abort
error: Ref refs/heads/master is at 55b388c141b1485b1acd9e050dbeb0eb90ef2ee7 but
expected b918ac16a33881ce00799bea63d9c23bf7022d67
fatal: Cannot lock the ref 'refs/heads/master'.
Could not move back to refs/heads/master

How can I get out of interactive rebase mode, and clean up all references to it? (git reset --hard succeeds, but doesn't drop me out of rebase mode.)

2

There are 2 answers

1
P Shved On BEST ANSWER

Try to follow the advice you see on the screen, and first reset your master's HEAD to the commit it expects.

git update-ref refs/heads/master b918ac16a33881ce00799bea63d9c23bf7022d67

Then, abort the rebase again.

0
VonC On

With Git 2.34 (Q4 2021), a git rebase --abort should be more reliable:

"git rebase <upstream> <tag>"(man) failed when aborted in the middle, as it mistakenly tried to write the tag object instead of peeling it to HEAD.

See commit 7740ac6, commit 1d18826, commit 35f070b (21 Sep 2021), and commit d045719, commit 1e14bc1, commit 0b7ae73, commit 54627db, commit 7390c65, commit e505f45, commit f20c1fb (13 Sep 2021) by Phillip Wood (phillipwood).
(Merged by Junio C Hamano -- gitster -- in commit 7cebe73, 06 Oct 2021)

rebase: dereference tags

Signed-off-by: Phillip Wood

A rebase started with 'git rebase <A> <B>'(man) is conceptually to first checkout <B> and run git rebase <A> starting from that state.
'git rebase --abort'(man) in the middle of such a rebase should take us back to the state we checked out <B>.

This used to work, even when <B> is a tag that points at a commit, until Git 2.20.0 when the command was reimplemented in C.
The command now complains that the tag object itself cannot be checked out, which may be technically correct but is not what the user asked to do.

Fix this old regression by using lookup_commit_reference_by_name() when parsing <B>.
The scripted version did not need to peel the tag because the commands it passed the tag to (e.g 'git reset'(man)) peeled the tag themselves.