Aborting and recovering a rebase gone wrong Jump to heading
Rebases go wrong in two phases. During the rebase, you hit the fifth conflict in a row, realise you rebased onto the wrong branch, or resolve a conflict badly and continue. After the rebase, you discover that a commit disappeared, a resolution dropped someone’s change, or the branch now contains commits that belong elsewhere. Both phases are recoverable, because rebase never destroys the original commits — it creates new ones and moves the branch name. The old commits remain reachable through ORIG_HEAD and the reflog. This page gives the exits during a rebase and the recovery after one, as part of interactive rebase workflows.
When to use this approach Jump to heading
- A rebase in progress has become confusing and you want out.
- A conflict was resolved wrongly and you have already continued past it.
- A completed rebase lost commits or changes.
- You rebased onto the wrong base, or with the wrong range — for ranges, see rebasing onto a new base with --onto.
Step 1 — Know the three exits during a rebase Jump to heading
While a rebase is stopped, three commands end or alter it, and they are not interchangeable.
git status # confirms a rebase is in progress and which commit stopped
git rebase --abort # restore the branch exactly as it was --abort discards all conflict resolutions made during this rebase. If you invested real effort, --quit keeps the commits applied so far reachable from HEAD, so you can inspect them before deciding.
git rebase --quit
git log --oneline -5 # the partially rebased commits, on a detached HEAD
git branch salvage/rebase-partial HEAD Step 2 — Redo a single bad resolution during the rebase Jump to heading
If you resolved a conflict, continued, and realise a few commits later that the resolution was wrong, you do not need to abort everything. The bad resolution is in a specific commit; let the rebase finish, then fix that commit with a fixup — or, if it is the current commit, amend it.
# The bad resolution is in the commit just applied — fix it now
git show HEAD -- src/conflicted/file.py
$EDITOR src/conflicted/file.py
git add src/conflicted/file.py && git commit --amend --no-edit
git rebase --continue If the conflicted file is a mess and you want the conflict back as it was, git checkout --conflict=zdiff3 -- <path> regenerates the conflict markers for the commit currently being applied.
Step 3 — Undo a completed rebase with ORIG_HEAD Jump to heading
When a rebase finishes, Git sets ORIG_HEAD to the branch tip before the rebase. Immediately after, resetting to it undoes the whole rebase.
git log --oneline -3 ORIG_HEAD # the pre-rebase tip
git reset --hard ORIG_HEAD ⚠️ SAFETY WARNING:
git reset --harddiscards uncommitted changes in the working tree. Commit or stash anything you want to keep first.ORIG_HEADis also overwritten by the next reset, merge or rebase, so use it only immediately after the rebase; otherwise use the reflog as in Step 4.
Step 4 — Recover later using the branch reflog Jump to heading
Days later, ORIG_HEAD is long gone, but the branch’s reflog records every position it has had. The entry just before “rebase (start)” or “rebase (finish)” is the pre-rebase tip.
git reflog show --date=iso feature/pdf | head -12
# 3a9e5d1 feature/pdf@{2026-10-01 16:42}: rebase (finish): refs/heads/feature/pdf onto 5c0f...
# 8b3e4f2 feature/pdf@{2026-10-01 11:05}: commit: Add page numbering # Compare the old and new versions before choosing what to restore
git range-diff 8b3e4f2...feature/pdf
# Restore entirely, or recover just the lost commit
git branch feature/pdf-before-rebase 8b3e4f2
git cherry-pick <lost-commit-sha> git range-diff is the best tool for spotting what changed in a rebase: it pairs each old commit with its new version and shows commits that disappeared.
Step 5 — Make future rebases easier to undo Jump to heading
A few settings reduce both the chance of a bad rebase and the cost of one.
git config --global rerere.enabled true # repeated conflicts are resolved the same way next time
git config --global merge.conflictStyle zdiff3 # see the base in every conflict
git config --global rebase.autoStash true # stash and restore uncommitted changes automatically
# Before a risky rebase, mark the current tip
git branch backup/feature-pdf-$(date +%H%M) Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
I pushed the bad rebase already. What now? Jump to heading
Restore the branch locally from the reflog, then push the restored version with --force-with-lease. Anyone who fetched the bad version must reset to the restored one. The steps match recovering from an accidental force-push.
Why does the rebase stop on commits that seem to have no conflict? Jump to heading
It stops on edit instructions, on failed exec commands, and when a commit becomes empty because its changes are already in the new base. For empty commits, --skip is usually right.
Is there any way a rebase can lose work permanently? Jump to heading
Only uncommitted changes discarded by reset --hard, or commits whose reflog entries have expired and been garbage-collected. Committed work is recoverable for weeks by default.
Related Jump to heading
- Interactive Rebase Workflows — the parent topic.
- Recovering Lost Commits with git reflog — the reflog in depth.
- Ours and Theirs During Merge vs Rebase — the most common cause of bad rebase resolutions.
- Reviewing a Force-Push with git range-diff — reading range-diff output.