Free reference
Git recovery cheat sheet
Not a list of git commands. A list of things that went wrong and the command that fixes each one, because that is how you actually need it at the moment you need it.
COMMITS
| Undo the last commit, keep the changes staged | git reset --soft HEAD~1 |
| Undo it, keep the changes unstaged | git reset --mixed HEAD~1 |
| Undo it and throw the work away | git reset --hard HEAD~1 |
| Undo a commit that is already pushed | git revert <sha> |
| Fix the last commit message | git commit --amend |
| Add a forgotten file to the last commit | git add file && git commit --amend --no-edit |
| Push history you rewrote | git push --force-with-lease |
| Committed on the wrong branch | git branch good; git reset --hard HEAD~1; git switch good |
| Take one commit from another branch | git cherry-pick <sha> |
FILES AND BRANCHES
| Discard changes in one file | git restore path |
| Discard everything uncommitted | git restore . |
| Unstage a file but keep the edits | git restore --staged path |
| Get one file from another branch | git restore --source=main -- path |
| Get back a file you deleted | git restore --source=HEAD~1 -- path |
| Deleted the wrong branch | git reflog, then git switch -c name <sha> |
| Stuck in detached HEAD | git switch - |
| Local branch is a mess, match the remote | git fetch && git reset --hard @{u} |
| Stashed something and forgot | git stash list; git stash show -p; git stash pop |
MERGES, REBASES, FORENSICS
| Merge went wrong, still in it | git merge --abort |
| Rebase went wrong, still in it | git rebase --abort |
| Rebase finished and it is wrong | git reset --hard ORIG_HEAD |
| Cherry-pick hit a conflict | git cherry-pick --abort |
| Find the commit that broke it | git bisect start; git bisect bad; git bisect good <sha> |
| Who changed these lines | git blame -L 20,40 path |
| Keep their side of a conflict | git checkout --theirs path && git add path |
| Committed a secret | Rotate the secret first. Rewriting history does not un-leak it. |
The parts people get wrong
These are the distinctions that cost real time. They are the reason this sheet exists rather than another list of commands.
git reset vs revert vs restore
reset moves the branch pointer. revert adds a new commit that undoes an old one. restore only touches files. Confusing the three is how work disappears.
Recovering lost commits with git reflog
reflog is your undo history and it keeps roughly 90 days. Check it before you panic. Almost nothing is actually gone.
git push --force-with-lease vs --force
--force-with-lease refuses to overwrite commits somebody else pushed. --force does not care. Use the lease.
HEAD~1 vs HEAD^ vs ORIG_HEAD
HEAD~1 is one commit back. HEAD^ is the same thing. HEAD~2 is two back. ORIG_HEAD is wherever you were before the last big move.
git switch and git restore vs git checkout
git switch and git restore split the two unrelated jobs git checkout used to do. Same results, far less ambiguity.
Can you recover from git reset --hard?
reset --hard discards uncommitted work with no reflog entry to recover it. That is the one command that really can lose something.