Session 4 · Undoing Things#
⏱ about 75 minutes · 🧰 you need: Session 3 done
The big idea#
The best thing about Git is that almost nothing is permanent. You can undo a commit, un-stage a file, fix a typo in the last message, or even recover work you thought you deleted. The skill is knowing which undo tool fits which situation.
Everyday example: writing with a pencil, a pen, and a marker. Pencil mistakes (not staged yet) are erased with restore. A wrong
page in the album (a commit) can be removed (reset) or cancelled with a new page saying “ignore the previous page” (revert).
First, a safe playground:
cd ~/git-lab
mkdir undo-lab && cd undo-lab
git init
echo "line 1" > story.txt && git add story.txt && git commit -m "Add story"
echo "line 2" >> story.txt && git commit -am "Add line 2"
echo "line 3" >> story.txt && git commit -am "Add line 3"
git log --oneline
c3c3c3c (HEAD -> main) Add line 3
b2b2b2b Add line 2
a1a1a1a Add story
Which undo do I need? (the cheat map)#
Situation |
Command |
|---|---|
I edited a file and want to throw the edit away |
|
I ran |
|
My last commit has a typo in the message or I forgot a file |
|
Undo the last commit(s) but keep my work |
|
Undo the last commit(s) and throw the work away |
|
Undo a commit that is already shared with others |
|
I lost a commit or did a bad reset |
|
1. Throw away edits in a file: git restore#
echo "oops, a terrible line" >> story.txt
git status -s
M story.txt
git restore story.txt
cat story.txt
line 1
line 2
line 3
The file is back to its last committed state.
Danger
git restore <file> cannot be undone. Git has no copy of edits you never committed or staged. Check git diff first.
2. Un-stage a file: git restore --staged#
echo "line 4" >> story.txt
echo "draft" > secret-notes.txt
git add .
git status -s
M story.txt
A secret-notes.txt
Oops, secret-notes.txt should not be in this commit. Take it out of the packing box (the file itself stays on disk):
git restore --staged secret-notes.txt
git status -s
M story.txt
?? secret-notes.txt
(Red arrows: git restore pulls a file from staging back into the folder; git restore --staged pulls it from the last commit back into staging.)
Finish the commit and clean up:
git commit -m "Add line 4"
rm secret-notes.txt
3. Fix the last commit: git commit --amend#
Typo in the message? Forgot a file? Amend replaces the last commit with a better one:
git commit --amend -m "Add line four to the story"
git log --oneline -1
d4d4d4d (HEAD -> main) Add line four to the story
Notice the ID changed (c3... style → d4d4d4d): amend creates a new commit and drops the old one. To add a forgotten file:
echo "credits" > credits.txt
git add credits.txt
git commit --amend --no-edit # keep the same message
Warning
Only amend commits you have not pushed. Amending rewrites history; if teammates already have the old commit, their copies will conflict with yours.
4. Undo commits with git reset#
reset moves your branch label back to an older commit. Imagine the branch is a bookmark; reset slides the bookmark backwards.
There are three strengths, and what differs is what happens to your changes:
Mode |
The commit |
Staging area |
Your files |
Use it when |
|---|---|---|---|---|
|
undone |
kept (still staged) |
kept |
“I want to re-commit it differently / combine commits” |
|
undone |
emptied |
kept |
“Undo the commit and unstage, let me redo |
|
undone |
emptied |
overwritten |
“Throw it all away” |
Try the safe ones first. Make a commit you regret:
echo "a bad idea" >> story.txt
git commit -am "Add a bad idea"
git log --oneline -2
e5e5e5e (HEAD -> main) Add a bad idea
d4d4d4d Add line four to the story
Undo the commit but keep the change in your folder:
git reset --soft HEAD~1
git status -s
M story.txt
The commit is gone, but the change is still staged. Edit, then commit again properly. Now the hard version:
git commit -m "Add a bad idea"
git reset --hard HEAD~1
cat story.txt
The bad idea is gone from history and from the file.
Danger
--hard throws away uncommitted work too. If you reset hard by mistake after committing, git reflog (below) can still save you. But uncommitted edits are gone for good.
Reset a single commit by ID#
HEAD~1 means “one commit before now”. You can also name a commit:
git reset --hard a1a1a1a # go back to the "Add story" snapshot
6. The safety net: git reflog#
Git quietly records every place your HEAD has been for about 90 days, even after a hard reset. This log is called the reflog.
git reset --hard HEAD~2 # "oh no, I meant HEAD~1"
git reflog
d4d4d4d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
f6f6f6f HEAD@{1}: revert: Revert "Add buggy change"
9a9a9a9 HEAD@{2}: commit: Add buggy change
d4d4d4d HEAD@{3}: reset: moving to d4d4d4d
...
Find the line from before your mistake and jump back to it:
git reset --hard f6f6f6f
git log --oneline -3 # everything is back
Reflog only records committed states. That is one more reason to commit early and often.
7. Other small rescues#
Need |
Command |
|---|---|
Rename or move a tracked file |
|
Delete a tracked file |
|
Stop tracking but keep the file |
|
Remove untracked files (dry run first!) |
|
Get one file from an older commit |
|
Common mistakes#
Mistake |
Fix |
|---|---|
Used |
Stay calm and run |
Amended or reset a commit that was already pushed |
Do not force-push on a shared branch. Use |
|
Cannot be recovered. From now on check |
|
|
Hands-on exercises#
Tryout 1 · Erase. In undo-lab, add a line junk to story.txt, then discard it with one command. Prove it is gone.
Answer
echo "junk" >> story.txt
git restore story.txt
git status # working tree clean
Tryout 2 · Fix a message. Commit with the message Add chapter tow (typo), then correct it to Add chapter two without creating an extra commit.
Answer
echo "chapter two" >> story.txt
git commit -am "Add chapter tow"
git commit --amend -m "Add chapter two"
git log --oneline -2
Tryout 3 · Rescue. Make two commits, run git reset --hard HEAD~2, then bring both commits back using the reflog.
Answer
echo "one" >> story.txt && git commit -am "Commit one"
echo "two" >> story.txt && git commit -am "Commit two"
git reset --hard HEAD~2
git reflog # find the line "commit: Commit two"
git reset --hard HEAD@{1} # or use that commit's ID
git log --oneline -3
Recap#
✅
git restore <file>discards edits (permanent!).git restore --staged <file>un-stages.✅
git commit --amendfixes the last commit (only if unpushed).✅
git reset --soft | --mixed | --hardmoves the branch back; hard also wipes your files.✅
git revert <commit>safely undoes a commit by adding a new one. Use it on shared history.✅
git reflogis the safety net for committed work.
Next: Session 5 · Branches.