Server

Recovering From Common Git Mistakes

By Prabath Thalangama· October 24, 2026· 3 min read
#git#recovery#troubleshooting

Introduction

Git rarely destroys data. Commits you can no longer see are usually still in the object database, reachable via the reflog, until garbage collection removes unreachable objects (default: ~90 days for reachable-from-reflog, 2 weeks for truly loose). Knowing the recovery path turns a panic into a one-liner.

The reflog

git reflog                     # every position HEAD has been in, newest first
git reflog show mybranch       # same for a specific branch
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
e4f5g6h HEAD@{1}: commit: Add feature
...

Recover to any state:

git reset --hard HEAD@{1}       # go back to where you were before the reset
# or, non-destructively:
git branch recovered e4f5g6h

Scenario recipes

"I committed to the wrong branch"

# You committed to main, meant to be on a feature branch. Nothing pushed.
git branch feature              # mark the current commit
git reset --hard HEAD~1         # move main back one (or --hard origin/main)
git switch feature              # your commit is here

"I need to undo my last commit but keep the changes"

git reset --soft HEAD~1         # commit undone, changes staged
git reset HEAD~1                # commit undone, changes unstaged (mixed, the default)
git reset --hard HEAD~1         # commit undone, changes GONE (reflog still has them)

"I need to undo a commit that's already pushed / shared"

git revert <sha>               # creates a NEW commit that inverts <sha>. Safe for shared history.
git revert -m 1 <merge-sha>    # revert a merge commit (keep parent 1)

Don't reset + force-push a shared branch; revert is the shared-history tool.

"I deleted a branch"

git reflog | grep <branch-name>          # find its last commit
# or:
git fsck --lost-found                     # dangling commits
git branch <branch-name> <sha>

"git stash pop had a conflict / I dropped a stash"

git fsck --no-reflog | awk '/dangling commit/ {print $3}' | \
  xargs -n1 git log --oneline -1          # find the stash commit
git stash apply <sha>

"I amended a commit and lost the original"

git reflog                                # HEAD@{1} is pre-amend
git reset --hard HEAD@{1}

"My working directory changes vanished (never committed)"

If they were never git added, Git never saw them — not recoverable via Git. If git added then lost (a bad checkout/reset --hard), dangling blobs may exist:

git fsck --lost-found
ls .git/lost-found/other/                 # blobs; inspect with git cat-file -p

Prevention: git stash before risky operations.

"I committed a secret"

# If NOT pushed and it's the last commit:
git rm --cached secrets.env
git commit --amend
echo "secrets.env" >> .gitignore

# If it's deeper in history or pushed — rewrite history:
git filter-repo --path secrets.env --invert-paths      # (git-filter-repo, not filter-branch)
git push --force-with-lease

Rotate the secret regardless. Once pushed, assume it's compromised — history rewrites don't reach forks, caches, or anyone who already cloned.

Verification and troubleshooting

git status
git log --oneline --graph --all
git reflog
git fsck --full --no-reflog
  • reset --hard and the reflog entry is already gone — very recent GC, or git gc --prune=now was run. Try git fsck --lost-found.
  • filter-repo "not a fresh clone" warning — it wants a clean mirror; heed it or pass --force, and re-clone elsewhere afterwards.
  • Force-push rejected — use --force-with-lease; if it still refuses, someone pushed after you — fetch and reconcile first.
  • Recovered a commit but it's detached HEAD — git branch <name> to keep it, otherwise the next GC reclaims it.
  • Team member's clone still has the secret after your history rewrite — they must re-clone or hard-reset their branches to the rewritten remote. And the secret is still burned — rotate it.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.