Recover work destroyed by a force push
Someone force-pushed and my commits are gone — how do I get them back?
Short answer
Your local clone still has the commits, and your reflog records where the branch pointed before the force-push overwrote it. Find that hash with git reflog, recover it to a branch, and push it back. If your local copy is already clean, a teammate's clone or the server's reflog may still have it.
git reflog show origin/main
git branch rescue <hash-from-before>
The remote-tracking ref's reflog records what origin pointed at before
Does this match your situation?
- Commits vanished from a shared branch after someone pushed with --force.
- git log no longer shows work you know was there.
- Your push is rejected because the remote history diverged unexpectedly.
Step-by-step fix
Stop pulling immediately
Every fetch or pull moves your remote-tracking references closer to the rewritten history and can push the useful reflog entries further out of reach. Work from what you already have locally first.
step 1git status git log --oneline -10Don't run git pull until you've recovered — you may overwrite your last local copy of the lost commits.
Check your own reflog for the branch
Your local reflog records every position your branch has held. If you had the commits before the force-push, they're listed here.
step 2git reflog git reflog show mainCheck the remote-tracking reflog too
Git keeps a separate reflog for origin/main showing what the remote pointed at each time you fetched. This often holds the pre-force-push hash even when your own branch didn't have it.
step 3git reflog show origin/mainRecover the commits onto a branch
Create a branch at the recovered hash and verify it contains what you expect before doing anything to the shared branch.
step 4git branch rescue a1b2c3d git log --oneline rescue -10 git diff main rescueRestore the shared branch carefully
Coordinate before pushing — the person who force-pushed may have done it deliberately. Usually the right move is to merge the rescued commits back rather than force-push over their work in turn.
step 5git switch main git merge rescue git push # only if the team agrees the rewrite was a mistake: git push --force-with-lease origin rescue:mainForce-pushing over a force-push without talking to the team just makes it worse.
Why this works
A force-push replaces the branch reference on the server, but it never deletes commit objects — not on the server, and certainly not in anyone's clone. Every developer who had fetched the branch still holds the full objects locally, and Git's reflogs record the previous values of both your local branch and your origin/* tracking refs. Recovery is therefore a matter of finding a hash that still exists somewhere and pointing a name at it again. This is the practical upside of Git being distributed: a force-push destroys one pointer, not the data.
If that didn’t work
- Ask every teammate to run git reflog and git log --oneline on their clone — someone will have the commits.
- Check CI: build logs and cached checkouts frequently record the exact commit hashes.
- On GitHub, the commits often remain reachable by direct URL, and pull request pages still list the old hashes.
- GitHub Enterprise and GitLab administrators can recover from the server-side reflog.
How to stop it happening again
- Enable branch protection on shared branches so force-pushes are simply rejected.
- Standardise on --force-with-lease, which aborts if the remote has moved since your last fetch.
- Never rebase or amend commits that have been pushed to a shared branch.
Commands used in this guide
git reflogThe undo history for everything - the single most important recovery command.
git branchList, create, rename and delete branches.
git pushUpload your commits to the remote repository.
git fsckScan the object database for orphaned commits and blobs the reflog no longer lists.
git fetchDownload new commits from the remote without changing any of your files.
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
Can I recover commits after someone force-pushed over them?
Usually. The commits still exist in every clone that had fetched them, and your local reflog — including the one for origin/main — records the hash the branch pointed at beforehand. Create a branch at that hash to bring the work back.
What is the difference between --force and --force-with-lease?
--force overwrites the remote branch unconditionally. --force-with-lease first checks that the remote is still where you last saw it and aborts if someone else has pushed, which prevents exactly the accident that destroys a colleague's work.
How do I stop force-pushes from happening again?
Enable branch protection on your hosting platform for main and any other shared branch. GitHub, GitLab and Bitbucket all support rejecting force-pushes outright, which is the only reliable prevention.
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 undo a commit that's already on the remote?
On a shared branch, use git revert <hash> — it adds a new commit that reverses the change, so nobody else has to do anything. Rewriting with reset plus a force-push is only appropriate on a branch you're certain nobody else has pulled.
Read the fix →Usually recoverableMy rebase went wrong and my commits are gone — how do I get them back?
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.
Read the fix →