Undoing Mistakes
Undoing Mistakes
After this page you can discard an unstaged edit, unstage a file, and rewrite the last commit before anyone else has it.
Three common “undo”s
| You did | You want | Command |
|---|---|---|
| Edited a tracked file, not staged | Throw the edit away | git restore <file> |
git add too soon |
Keep the edit, leave it out of the next commit | git restore --staged <file> |
| Last commit message (or last commit contents) is wrong, not pushed | Replace that commit | git commit --amend |
These are safe on a laptop branch nobody has fetched. After git push, amending rewrites a hash other people may have. Chapter 9 and chapter 11 cover that case. Chapter 17 (reflog) is the safety net when you went too far.
restore <file> restore --staged commit --amend
working ← index index ← HEAD A ← B ← C
A ← B ← C' (C gone from main)
Discard unstaged work
cd ~/desk/desk-api
echo "oops" >> README.md
git restore README.mdThe working-tree file matches the index again. The “oops” line is gone. Git cannot get it back from Git; your editor’s undo might.
Restore one file from HEAD even if it was staged:
git restore --source=HEAD --worktree --staged README.mdThat is “make this file look like the last commit, in both index and working tree.”
Unstage, keep the edit
echo "keep me" >> README.md
git add README.md
git restore --staged README.md
git statusThe line is still in the file. It is not in the index. The next git commit will not include it until you git add again.
Older docs say git reset HEAD README.md for the same unstage. This book uses git restore --staged.
Amend the last commit
You just committed and noticed a typo in the message:
git commit --amend -m "Add ping helper"You forgot a file:
git add src/ping.py
git commit --amend --no-edit--no-edit keeps the old message. --amend replaces the last commit with a new one (new hash) whose parent is the same as before. git log no longer shows the old hash as main. The old commit is still in the reflog for about 30 days (chapter 17).
Amend only when:
- it is the latest commit on this branch, and
- you have not pushed it, or you are sure no one else built on it.
Revert is a new commit
git revert <hash> adds a commit that undoes a previous one. Use it on history other people already have. Chapter 10 is revert and cherry-pick. For a local last-commit mistake, amend. For an old published mistake, revert.
rm and mv
git rm src/old.py # stop tracking and delete the file
git rm --cached secrets.env # stop tracking, keep the file on disk
git mv src/ping.py src/health.py
git status
git commit -m "Rename ping to health"git mv is mv plus git add of the rename. Git detects renames in diffs even if you mv and add by hand; git mv is the tidy form.
If you are lost
git status
git log --oneline -5Status tells you which of the three trees disagree. Log tells you where main points. The hands-on page next builds a tiny desk-api from scratch so you can practice the whole loop, including one amend.