Skip to content

Cheatsheet: Undoing things

Git stores snapshots. Every other command is just navigating those snapshots.

ScenarioCommand
Discard working-directory changesgit restore <file>
Unstage a staged filegit restore --staged <file>
Fix last commit (message or content)git commit --amend [-m "new message"]
Undo local-only commit, keep changes stagedgit reset --soft HEAD~1
Undo local-only commit, keep changes in working dirgit reset HEAD~1
Undo local-only commit, discard everythinggit reset --hard HEAD~1
Undo pushed commit (safe)git revert <commit-hash>
Recover from destructive operationgit reflog then git reset --hard <hash>
ModeCommit pointerStagingWorking dirUse case
--soft HEAD~1Back 1KEPTKEPT”Redo commit with different message or more files”
--mixed HEAD~1 (default)Back 1CLEAREDKEPT”Re-stage piece by piece, maybe as multiple commits”
--hard HEAD~1Back 1CLEAREDCLEARED”Throw it all away”, destructive, use reflog if regret

HEAD~N means N commits back. HEAD alone means current.

Has the commit been pushed?

  • No then git reset or git commit --amend are safe (you’re rewriting history that only you have)
  • Yes then use git revert; never git reset + git push --force

After any destructive operation, run:

Terminal window
git reflog

You see output like:

abc1234 HEAD@{0}: reset: moving to HEAD~3
def5678 HEAD@{1}: commit: Add feature X
ghi9012 HEAD@{2}: commit: Refactor parser

To recover:

Terminal window
git reset --hard HEAD@{1} # via reflog reference
# or
git reset --hard def5678 # via commit SHA

The reflog stores ~90 days. If you realize a week later, you’re fine. If you realize three months later, hope someone else has it.

L5 starts Phase 2 with branches, parallel sequences of snapshots. The snapshot mental model becomes the most useful here because branches are just pointers into the snapshot graph. You learn git branch, git checkout / git switch, and git merge. Branches are how you collaborate.