By admin , 29 April 2026

What you will achieve

You will deliberately mess up a rebase, then recover using the reflog and ORIG_HEAD. The recovery patterns work for any rewrite gone wrong - botched interactive rebase, accidental drop, mid-rebase confusion.

Setup: a sandbox with real commits

mkdir rebase-recovery && cd rebase-recovery
git init
for i in 1 2 3 4 5; do
  echo "$i" > file.txt
  git add . && git commit -m "Commit $i"
done
git log --oneline
# 5 commits, ready to break

Disaster 1: accidentally dropped commits

Run an interactive rebase and "drop" a commit:

git rebase -i HEAD~4
# Editor opens. Change "pick" to "drop" for one commit. Save.

Verify the loss:

git log --oneline
# one fewer commit than before

Recovery 1: ORIG_HEAD

Git automatically saves the pre-rebase tip in ORIG_HEAD:

git reset --hard ORIG_HEAD
git log --oneline
# all 5 commits restored

Disaster 2: rebase conflict resolution gone wrong

Trigger conflicts and resolve them badly:

git checkout -b feature HEAD~2
echo "feature change" >> file.txt
git commit -am "Feature change"
git rebase main
# conflicts

Suppose you resolved by keeping the wrong side and continued. Now your branch has wrong content.

Recovery 2: reflog

git reflog
# HEAD@{0} rebase finished
# HEAD@{1} rebase: applying ...
# HEAD@{2} rebase (start): checkout main
# HEAD@{3} commit: Feature change   <-- pre-rebase tip
git reset --hard HEAD@{3}

You are back to the pre-rebase state. Re-rebase, this time with care.

Disaster 3: rebase, then more work, then realise rebase was wrong

You rebased, made several commits, then realised the rebase introduced a regression. ORIG_HEAD is overwritten by the new commits. Use the reflog:

git reflog
# find the SHA before "rebase (start)"
git reset --hard <sha-before-rebase>

You will lose the post-rebase commits. Cherry-pick the ones you want to keep first:

# From the bad state, save the good commits onto a temp branch:
git branch save-work HEAD~2..HEAD     # creates a branch at the good commits
git reset --hard <sha-before-rebase>
git cherry-pick save-work
git branch -D save-work

Disaster 4: force-pushed the bad rebase

You rebased badly and force-pushed before noticing. The remote has the broken history. Recovery options:

  • Local reflog still has the original. Reset and force-push again, restoring the good state.
  • A teammate has a clone with the original. They push their copy back.
  • The host has a "branch protection" log or activity log. Some hosts retain pushed SHAs for hours; support can sometimes recover them.
# Local recovery
git reflog
git reset --hard <good-sha>
git push --force-with-lease

Disaster 5: rebase ate the wrong parent

You rebased a feature branch onto the wrong base. The branch now has unrelated commits at its root. Reset to ORIG_HEAD and re-rebase onto the correct base:

git reset --hard ORIG_HEAD
git rebase main      # the correct base

Preventing future disasters

Make a backup branch before risky operations

git branch backup-before-rebase
git rebase -i HEAD~10
# If anything goes wrong:
git reset --hard backup-before-rebase
git branch -D backup-before-rebase

Increase reflog expiry

git config gc.reflogExpire 365.days
git config gc.reflogExpireUnreachable 90.days

Push before rebasing

If you push the branch (perhaps to a backup remote) before rebasing, the original commits are preserved off-machine.

git push backup HEAD:my-branch-backup
git rebase ...

Enable rerere

git config --global rerere.enabled true

"Reuse recorded resolution" remembers conflict resolutions so a re-do of the rebase resolves them automatically.

The mental model

Rebase rewrites commits, but the originals do not vanish - they linger as orphan commits in the object database, reachable via reflog for ~90 days. git reset --hard moves the branch pointer back; the commits are still there. Recovery is almost always one git reflog away.

The discipline

Botched rebase is not a disaster; it is a five-minute setback. Practise the recovery once on a sandbox, and the panic disappears for good.