After a bad force push or hard reset, the commits are usually still in someone's repository. Find the old branch tip with git reflog on a machine that had it, create a branch at that commit, and push it somewhere safe. Act soon, because reflog entries expire.
What the reflog records
Git's reflog records when the tips of branches and other references were updated in the local repository. The HEAD reflog also records branch switching. It lets you ask where a branch pointed earlier, using syntax such as a branch name with a time or a step count in braces.
Two limits matter in an incident:
- The reflog is local. Your colleague's reflog and the server's history are different things. The machine that last had the old tip is the one to search.
- Entries expire. Git documents defaults of 90 days for reachable entries and 30 days for entries that are not reachable from the current branch tip. Commits that nothing refers to can also be removed by garbage collection later. So do not wait.
Runbook
Step 1: stop the spread. Ask people to pause fetching with pruning and to avoid deleting local clones or running cleanup. Tell them not to push over the branch again. If the branch is protected, restore protection after you finish.
Step 2: find a machine with the old tip. Anyone who pulled the branch before the force push has it. A CI runner's workspace may also hold it. Ask in the incident channel.
Step 3: read the reflog. On that machine:
git reflog show main
You will see lines of recent updates with short hashes. Find the entry just before the overwrite. You can also inspect the history at an earlier point, for example with a time reference, to confirm it is the right state.
Step 4: point a branch at it.
git branch recovered-main abc1234
git log --oneline recovered-main
Replace the hash with the one you found. Check that the history looks right and that the latest work is there.
Step 5: put it back safely. Push the recovered branch under a new name first, so a copy exists on the server. Then decide how to restore the original branch name. Pushing back with a force flag is a second force push, so announce it, and prefer a lease based push so you do not overwrite newer work by accident.
Step 6: tell everyone to reconcile. People who pulled after the bad push have the wrong history. Have them move their local branch to the recovered one rather than merging the two, or they will reintroduce the problem.
If no one has the old tip
Check the hosting provider's own records and your CI artifacts. Pull requests that referenced the old commits may still show them. Backups of the repository, if you keep mirrors, are the last resort. If you have none, the incident is a reason to start.
Prevent the next one
- Protect main branches against force pushes.
- Use force with lease instead of plain force.
- Keep a regular mirror of important repositories.
- Practice this recovery once on a test repository, so the first time is not during an incident.
For the larger case where a whole repository is gone, see restoring a deleted GitHub repository.
Quick check
Is the reflog stored on the server?
No. It is local to each repository clone, so the machine that last had the branch is the one to check.
How long do reflog entries last?
Git documents defaults of 90 days for reachable entries and 30 days for unreachable ones, so recover quickly.
Sources
Last reviewed: 19 October 2026.