Push & pull problemsUsually recoverable

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.

quick fix
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

  1. 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 1
    git status
    git log --oneline -10
    

    Don't run git pull until you've recovered — you may overwrite your last local copy of the lost commits.

  2. 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 2
    git reflog
    git reflog show main
    
  3. Check 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 3
    git reflog show origin/main
    
  4. Recover 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 4
    git branch rescue a1b2c3d
    git log --oneline rescue -10
    git diff main rescue
    
  5. Restore 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 5
    git switch main
    git merge rescue
    git push
    
    # only if the team agrees the rewrite was a mistake:
    git push --force-with-lease origin rescue:main
    

    Force-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 reflog

The undo history for everything - the single most important recovery command.

git branch

List, create, rename and delete branches.

git push

Upload your commits to the remote repository.

git fsck

Scan the object database for orphaned commits and blobs the reflog no longer lists.

git fetch

Download 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

← All Git Rescue guides