Recover commits lost during a rebase
My rebase went wrong and my commits are gone — how do I get them back?
Short answer
The pre-rebase commits are still in the object database. git reflog shows the position from before the rebase started, and ORIG_HEAD is a shortcut to it — git reset --hard ORIG_HEAD usually restores everything in one command.
git reset --hard ORIG_HEAD
Git saves the pre-rebase position in ORIG_HEAD automatically
Does this match your situation?
- A rebase finished but commits are missing from git log.
- You resolved conflicts wrongly and want to start over.
- You dropped or squashed a commit in interactive rebase by accident.
- A rebase is stuck partway and you want out.
Step-by-step fix
Still mid-rebase? Abort it
If Git is still in the middle of the rebase, aborting restores the original branch completely. Nothing is lost and you can try again.
step 1git rebase --abortRebase finished badly? Use ORIG_HEAD
Git writes the branch's previous tip into ORIG_HEAD before any rebase, merge or reset. That makes recovery from a just-completed rebase a single command.
step 2git reset --hard ORIG_HEADORIG_HEAD is overwritten by the next rebase, merge or reset — so use it right away or grab the hash from the reflog instead.
Otherwise, read the reflog
The reflog logs every step the rebase took. Look for the entry immediately before the 'rebase (start)' line — that's your original branch tip.
step 3git reflog # typical output: # a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature # f4e5d6c HEAD@{5}: rebase (start): checkout main # 9a8b7c6 HEAD@{6}: commit: The work you want back ← this oneRestore onto a branch you can compare
Rather than resetting immediately, create a branch at the recovered commit. You can then diff it against the rebased branch and keep whichever is right.
step 4git branch pre-rebase 9a8b7c6 git log --oneline pre-rebase -10 git diff pre-rebase feature # happy with it? point your branch back: git switch feature git reset --hard pre-rebaseRecover a single dropped commit
If the rebase was mostly right and you only lost one commit, cherry-pick it back rather than resetting everything.
step 5git cherry-pick 9a8b7c6
Why this works
Rebase never edits commits — it creates new ones with the same changes and different parents, then moves the branch pointer to the new chain. The originals become unreferenced but remain in .git/objects, and every step is journalled in the reflog. ORIG_HEAD is a convenience reference Git sets to the previous tip before any operation that moves the branch significantly, which is why it so often points exactly where you want to go.
If that didn’t work
- Run git fsck --lost-found and look through dangling commits with git log --oneline <hash>.
- If the branch was pushed before the rebase, git fetch origin and recover from origin/your-branch.
- Check whether a colleague or CI still has the pre-rebase commits.
How to stop it happening again
- Create a safety branch before rebasing: git branch backup-$(date +%s).
- Use git rebase --autostash so uncommitted work isn't in the firing line.
- Never rebase a branch that's already shared — merge it instead.
- Turn on rerere so repeated conflict resolutions replay themselves.
Commands used in this guide
git reflogThe undo history for everything - the single most important recovery command.
git rebaseReplay your commits on top of another branch to produce a straight, linear history.
git resetMove the current branch pointer, optionally rewriting the index and your files.
git cherry-pickCopy one specific commit onto your current branch.
git fsckScan the object database for orphaned commits and blobs the reflog no longer lists.
Still stuck?
Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.
Browse all guides →Frequently asked questions
What is ORIG_HEAD in Git?
A reference Git automatically sets to the previous position of HEAD before a rebase, merge or reset. git reset --hard ORIG_HEAD therefore undoes the most recent one of those operations. It's overwritten each time, so it only helps for the operation you just ran.
Can I undo a completed rebase?
Yes. Use git reset --hard ORIG_HEAD immediately after, or find the pre-rebase commit in git reflog and reset to that hash. The original commits remain in the object database until garbage collection prunes them.
How do I get back a commit I dropped in interactive rebase?
Find its hash in git reflog — dropped commits still appear there — then git cherry-pick it back onto your branch. If several were lost, resetting to the pre-rebase commit and redoing the rebase is usually simpler.
Related rescue guides
I ran git reset --hard and lost my commits — how do I undo it?
Committed work is almost never really gone. git reflog lists every position HEAD has held, including the one just before your reset, so you can jump straight back to it with git reset --hard HEAD@{1}. Uncommitted changes that the reset wiped are a different story — those are only recoverable if they had been staged at some point.
Read the fix →Usually recoverableI deleted a Git branch — how do I get it back?
Deleting a branch removes a pointer, not the commits. Find the branch's last commit hash in the reflog and recreate the branch at that hash with git branch <name> <hash>. If the branch was pushed, the copy on the server may still exist and can simply be fetched back.
Read the fix →Always fixableHow do I combine multiple commits into a single commit?
git rebase -i HEAD~n opens an editor where you mark commits as squash or fixup to fold them into the one above. For a quick all-in-one collapse, git reset --soft HEAD~n followed by a fresh commit achieves the same result with no editor at all.
Read the fix →Always fixableGit says I have merge conflicts — how do I fix them?
Git pauses and marks the clashing sections with <<<<<<<, ======= and >>>>>>>. Edit each file to the version you actually want, delete the markers, git add the file, then git merge --continue. If it gets overwhelming, git merge --abort returns you to exactly where you started.
Read the fix →