Git Course 0%

The undo map

Intermediate ≈ 12 min

What you will learn

  • Which command matches which mistake
  • The one question that decides between rewriting and reverting
  • What each fix costs you, and what it costs other people

After this lesson you can

  • I can pick the right undo without guessing, and explain why

Why this matters

Almost every Git mistake is one of six situations, and each has one right answer. This page is the map; the lessons after it are the detail. If you read only one page in this section, read this one.

The map

The undo map: what went wrong, and the command that fixes it Six cards. First, I changed a file and want the committed version back: git restore the file, safe, and it discards the edit for good. Second, I staged something by mistake: git restore --staged the file, safe, and the edit is kept. Third, my last commit is wrong and I have not pushed: git commit --amend, which rewrites that commit. Fourth, a commit is wrong and it is already pushed: git revert the hash, safe on shared branches because it adds a new commit. Fifth, I want to move my branch back in history and have not pushed: git reset, which rewrites history. Sixth, I need to park unfinished work: git stash, safe. A legend explains that green means safe anywhere, amber means safe only before pushing, and each card says what it does to uncommitted work. Undo an edit to a file not staged, not committed git restore <file> Safe for others. Your edit is gone for good. Unstage something added by mistake git restore --staged <file> Safe. The edit itself is kept. Park unfinished work to switch branch or pull git stash Safe. Comes back with git stash pop Fix the last commit message, or a forgotten file git commit --amend Rewrites that commit. Only before pushing. Move the branch back drop recent commits git reset <target> Rewrites history. Only before pushing. Undo a pushed commit already on the shared branch git revert <hash> Adds a new commit. The only safe choice here. safe on shared branches rewrites history: only before pushing The question that decides the column is always the same: has this been pushed where other people can see it? If yes, revert. If no, amend or reset are available and tidier.
Six situations and the command for each. Green is safe on shared branches; amber rewrites history and is only safe before pushing.

The question that decides everything

Before choosing, ask: has this been pushed where other people can see it?

Answer What is available
No, it is local Anything: amend, reset, rebase. You are rearranging your own furniture.
Yes, it is pushed Add a new commit that undoes the old one: git revert. Rewriting means everyone else's history stops matching yours (lesson 12.8).

That single question resolves most of the confusion between reset and revert, which is the pair people mix up most.

The six situations

1. I changed a file and want the committed version back

Terminal
$ git status --short
 M docs/faq.md
Terminal
$ git restore docs/faq.md

Nothing is printed, and git status is clean again. The edit is gone for good: Git never recorded it, so the reflog cannot help. This is the most genuinely destructive command in everyday use, which is why it is worth pausing on.

2. I staged something by mistake

Terminal
$ git add docs/getting-started.md
$ git status --short
M  docs/getting-started.md
Terminal
$ git restore --staged docs/getting-started.md
$ git status --short
 M docs/getting-started.md

The M moved from the left column to the right: staged, then merely modified. Your edit is kept; only the staging is undone. Note how similar the two commands are, and how different the consequences: --staged is the safe one.

3. My last commit needs fixing, and I have not pushed it

Terminal
$ git commit -am "docs: add Windos section"
$ git log --oneline -1
2c4263b docs: add Windos section
Terminal
$ git commit --amend -m "docs: add Windows section"
$ git log --oneline -1
97fc096 docs: add Windows section

The hash changed, which is the sign that this rewrites history: the old commit is replaced rather than edited. Fine while it is yours alone, a problem the moment it is pushed. git commit --amend --no-edit also works for "I forgot a file": stage the file, then amend.

4. A commit is wrong and it is already pushed

Terminal
$ git revert 97fc096
[main 4bd6eb3] Revert "docs: add Windows section"
 1 file changed, 2 deletions(-)
Terminal
$ git log --oneline -3
4bd6eb3 Revert "docs: add Windows section"
97fc096 docs: add Windows section
d3b92ec chore: add CI configuration and contributing guide

Both commits are in the history: the mistake and its undo. That is the point. Everyone else's clone still matches yours, and nobody has to do anything. This is the only safe undo for shared work.

5. I want to move my branch back, and I have not pushed

Terminal
$ git reset --soft HEAD~1
$ git status --short
A  .github/workflows/ci.yml
A  .gitlab-ci.yml
A  .markdownlint.json
A  CONTRIBUTING.md

The commit is gone from the branch and its changes are staged, ready to be re-committed differently. That is --soft; --mixed and --hard differ in where the changes land, which is lesson 12.4 and worth reading before using --hard.

6. I need to park unfinished work

Terminal
$ git stash push -m "windows draft"
Saved working directory and index state On main: windows draft
Terminal
$ git stash list
stash@{0}: On main: windows draft
Terminal
$ git stash pop
 M docs/getting-started.md
?? notes.txt

The tree is clean while the work waits, and pop brings it back. Note that plain git stash leaves untracked files where they are; git stash -u includes them.

The pairs people confuse

These look alike The difference
git restore <file> and git restore --staged <file> The first discards your edit; the second only unstages it
git reset and git revert Reset rewrites the branch; revert adds a commit. Pushed means revert
git commit --amend and a new commit Amend replaces; a new commit adds. Pushed means add
git stash pop and git stash apply Pop removes the stash after restoring it; apply keeps it
git restore and git checkout restore is the modern, clearer name; checkout still works and does more things (command page)

How to do it

The map above, as commands. Before any of them, run git status: it tells you which situation you are in, and it often prints the exact command you need in its hints.

Common mistakes

  • Reaching for reset on pushed work. Use revert; the pushed commit is already in other people's clones.
  • Typing git restore <file> when you meant --staged. One discards your work, the other does not.
  • Amending a pushed commit, which forces everyone else to reconcile a history that no longer matches.
  • Using git stash as storage. It is a pocket, not a drawer; stashes accumulate and get forgotten (command page).
  • Running the fix before reading git status, which usually tells you which situation you are in.

Try it yourself

Goal: walk the whole map once, in a repository where nothing matters.

  1. Edit docs/faq.md, check git status --short, then undo it with git restore.
  2. Edit it again, git add it, and undo only the staging with git restore --staged. Confirm the edit survived.
  3. Commit with a deliberately misspelled message, then fix it with git commit --amend. Note that the hash changed.
  4. Commit a real change, then git revert it. Note that both commits are in git log.
  5. Make an edit, git stash push -m "test", confirm the tree is clean, then git stash pop.

Expected result: five undos performed, and a feel for which ones changed history and which added to it.

Show solution

Step 3 and step 4 are the pair to remember. Amend changed the hash, which means the old commit no longer exists; revert added a commit, which means nothing was removed. Everything else in this section is a variation on that distinction.

Check yourself

1. You pushed a commit that turned out to be wrong. Which command?
2. What is the difference between git restore <file> and git restore --staged <file>?
3. What tells you that git commit --amend rewrote history?

Key terms

Restore Revert Staged Stash Rewriting history