How I Recover from Common Git Mistakes
Most Git mistakes are recoverable. The difficult part is choosing a command that fixes the right layer—working tree, staging area, commit, or branch—without deleting something else.
Before using reset --hard or clean, make a copy of work you cannot reproduce. The safer commands come first below; the destructive reset is deliberately last.
Find a commit that seems lost
git reflog records where HEAD and local branch references have pointed. I use it when a reset, rebase, or deleted branch makes a commit look lost.
git reflog
# Find the entry before the unwanted operation, then create a recovery branch.
git branch recovery HEAD@{index}
Creating a branch is safer than immediately resetting your current one. Once you have inspected recovery, you can decide whether to reset, cherry-pick, or keep it.
Add a forgotten change to the last commit
If the last commit is still local, stage the missing file and amend it:
git add path/to/file
git commit --amend --no-edit
Amending rewrites the commit. Avoid it after pushing to a branch other people may already use; a small follow-up commit is usually less disruptive there.
To change only the last commit message, run:
git commit --amend
Move a local commit off the wrong branch
Suppose the latest commit belongs on a feature branch but was made on main. First create the correct branch at the current commit, then move main back:
git branch feature-name
git reset --hard HEAD~
git switch feature-name
This assumes the working tree is clean and the commit has not been shared. If it has already reached a shared main, keep its history intact and revert it there after cherry-picking it to the right branch:
git switch feature-name
git cherry-pick <commit>
git switch main
git revert <commit>
See changes that are already staged
Plain git diff shows unstaged changes. After git add, use:
git diff --staged
I run this before committing. It shows exactly what the next commit will contain.
Undo an older shared commit
git revert creates a new commit that reverses another one, so it is usually the right choice for shared history:
git log --oneline
git revert <commit>
Review the result carefully. Reverting an old commit may conflict with later work that changed the same lines.
Restore one file from an older commit
Modern Git has a command that says exactly what it does:
git log -- path/to/file
git restore --source=<commit> -- path/to/file
git add path/to/file
git commit -m "Restore file from <commit>"
The older git checkout <commit> -- path/to/file syntax still works, but restore is clearer.
Make a local branch match its remote
This removes local commits, working-tree changes, and untracked files. I would only use it after confirming the branch name and saving anything important elsewhere.
git fetch origin
git switch main
git reset --hard origin/main
git clean -d --force
Before the final command, git clean -d -n previews what would be deleted. That one dry run can save files Git does not track and therefore cannot recover.
The pattern behind all of these fixes is simple: inspect first, preserve a reference when possible, and use destructive commands only after the target is unambiguous. Git usually keeps more recovery information than it first appears to.