Learning Objectives
By the end of this lesson you will be able to:
- Choose the correct undo command from the situation, without reasoning from first principles
- Apply the one question that eliminates most of the options immediately
- Recover from having chosen the wrong one
- Explain your choice to a colleague looking over your shoulder
The Question That Sorts Everything
Is this commit outside my machine?
If yes → git revert. Nothing else is safe, and no other consideration overrides this.
If no → the local tools are available: reset, restore, rebase -i, commit --amend.
You have now eliminated most of the possibilities in about two seconds, which is exactly what you want when production is broken and somebody is standing behind you.
To answer it concretely:
git log --oneline origin/main..HEAD
Anything that command lists is local-only, and fair game. Anything it does not list has been published.
The Full Decision Table
| What you want to undo | Command |
|---|---|
| Edits to a file, not yet staged | git restore <file> |
| Staging of a file, keeping the edits | git restore --staged <file> |
| All uncommitted changes in tracked files | git reset --hard |
| Untracked files (never committed) | git clean -n then git clean -fd |
| The last commit's message only | git commit --amend |
| The last commit, keeping changes staged | git reset --soft HEAD~1 |
| The last commit, re-deciding what to stage | git reset HEAD~1 |
| The last three commits, entirely | git reset --hard HEAD~3 |
| An older commit on a local branch | git rebase -i and drop |
| Any commit that has been pushed | git revert <sha> |
| A merge that has been pushed | git revert -m 1 <sha> |
| A rebase you just finished | git reset --hard ORIG_HEAD |
Two rows are worth pointing at.
git clean appears here because "undo" often means untracked files — a directory of generated reports, an accidental node_modules. restore and reset --hard both leave those completely alone. Module 7 covers it properly.
--amend is a rewrite, even though it feels gentle. Amending a pushed commit needs a force-push and breaks the Golden Rule exactly as reset would.
Under Pressure
When it is urgent, three habits prevent nearly every bad outcome.
Run git status first. It tells you what is staged, what is modified, whether a merge or rebase is in progress, and it names the right command for each. Ten seconds.
Prefer the reversible option when unsure. git stash before a destructive command. git branch backup/before-fix before rewriting a branch. Both take a second and both make the next step undoable.
Say what you are about to do out loud if someone is watching. "I'm going to revert the merge commit, keeping main as the mainline." If it is wrong, that sentence is where they catch it — not the command.
When You Choose Wrong
Nearly everything is recoverable, and knowing which is which removes the panic.
| Mistake | Recovery |
|---|---|
Wrong reset, commits gone |
git reset --hard ORIG_HEAD, or find it in git reflog |
| Deleted a branch | git reflog, then git branch <name> <sha> |
| Bad rebase, finished | git reset --hard ORIG_HEAD |
| Reverted the wrong commit | git revert the revert |
restore over uncommitted edits |
Nothing. They were never stored |
clean -fd over untracked files |
Nothing. They were never stored |
The pattern is the line dividing the table. Anything that was ever committed can be recovered. Anything that was not, cannot. That single sentence is the whole risk model of Git, and it is why "commit early, commit often" is advice about safety rather than tidiness.
Pro Tip: When you genuinely do not know which command to use,
git stashand then think. It saves the working tree, index included, gives you a clean state to experiment in, andgit stash popputs everything back. It is the cheapest safety net in this entire trail.
For the Tester
Two undo situations come up constantly in QA work.
"I broke my test environment's repo." Almost always: git reset --hard origin/<branch> plus git clean -fd. Together they make the working copy identical to the remote, which is exactly what a test environment should be.
"Did this commit cause the regression?" Revert it on a scratch branch, build, test, throw the branch away. A definitive answer in ten minutes, and nothing at risk.
Key Takeaways
- One question first: is the commit outside my machine? If yes,
revert, and nothing else git log --oneline origin/main..HEADanswers that question concretelyrestorefor files,resetfor the branch pointer,revertfor published history,cleanfor untracked files--amendrewrites history too, despite feeling harmlessgit statusbefore, and something reversible — a stash or a backup branch — when unsure- Everything ever committed is recoverable; nothing else is