04 - Fixing Mistakes
#04 - Fixing Mistakes
##The Good News
Git is designed to be nearly impossible to permanently lose work — as long as you committed it. This module teaches you how to undo mistakes at every stage of the workflow.
The key question is always: how far has the mistake gone?
1
2
3
Stage 1: Wrong file staged (but not committed yet) easiest to fix
Stage 2: Wrong file committed (but not pushed) still easy
Stage 3: Need to understand what went wrong use git log / git diff
##Mistake 1: Staged the Wrong File
The situation: You ran git add on the wrong file (or more files than you meant to). You have not committed yet.
Let’s recreate it:
1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir practice && cd practice && git init
touch good_file.py bad_file.py
git add good_file.py
git commit -m "add good_file"
#Now make changes to both files
echo "good code" > good_file.py
echo "oops not ready" > bad_file.py
#Accidentally stage both
git add good_file.py bad_file.py
git status
Expected:
1
2
3
Changes to be committed:
modified: bad_file.py
modified: good_file.py
Fix — unstage bad_file.py:
1
2
git restore --staged bad_file.py
git status
Expected:
1
2
3
4
5
Changes to be committed:
modified: good_file.py
Changes not staged for commit:
modified: bad_file.py
bad_file.py is back in the working directory — unchanged, just unstaged. Now commit only what you intended:
1
git commit -m "Update good_file with new logic"
git restore --staged <file>is the modern command (Git 2.23+). The older equivalent isgit reset HEAD <file>— both do the same thing.
Unstage everything at once:
1
git restore --staged .
##Mistake 2: Committed the Wrong File
The situation: You committed something you should not have. The commit is in your local history but you have NOT pushed yet.
1
2
3
4
5
6
#Simulate the mistake
echo "SECRET_KEY=abc123" > .env
git add .env
git commit -m "add config file"
git log --oneline
Expected:
1
2
f8a3c1b add config file the bad commit
9d2e4a0 add good_file
Fix — undo the last commit but keep the file:
1
2
git reset --soft HEAD~1
git status
Expected:
1
2
Changes to be committed:
new file: .env
The commit is gone from history, but .env is still staged. Now unstage it and decide what to do:
1
2
git restore --staged .env
git status
Expected:
1
2
Untracked files:
.env
Add .env to .gitignore so this never happens again:
1
2
3
echo ".env" >> .gitignore
git add .gitignore
git commit -m "Add .gitignore to exclude .env"
##Understanding Reset Modes: Soft vs Hard
git reset moves the HEAD pointer back to a previous commit. The three modes differ in what they do to your files after moving.
###The Three Areas (refresher)
1
Working Directory Staging Area Repository (commits)
###–soft: Undo commit, keep changes staged
HEAD moves back, but your files stay staged. Perfect for “I committed too soon, let me add one more thing first.”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#Make two commits
echo "line 1" > notes.txt && git add notes.txt && git commit -m "add line 1"
echo "line 2" >> notes.txt && git add notes.txt && git commit -m "add line 2"
git log --oneline
#f1a2b3c add line 2
#a4b5c6d add line 1
#Undo the last commit, keep changes staged
git reset --soft HEAD~1
git log --oneline
#a4b5c6d add line 1 last commit is gone
git status
#Changes to be committed:
# modified: notes.txt but the change is still staged!
Use --soft when you want to recommit with a better message, or combine with the next commit.
###–mixed (default): Undo commit AND unstage
HEAD moves back and the staging area is cleared, but your file edits remain.
1
2
3
4
5
6
git reset HEAD~1
#same as: git reset --mixed HEAD~1
git status
#Changes not staged for commit:
# modified: notes.txt change is in working dir, not staged
Use --mixed when you want to re-review and re-stage your changes before committing.
###–hard: Undo commit AND discard all changes
HEAD moves back, staging is cleared, AND your working directory is reverted. The changes are gone.
1
2
3
4
git reset --hard HEAD~1
git status
#nothing to commit, working tree clean changes are GONE
Use --hard only when you are 100% sure you want to throw away those changes.
###Comparison Table
| Mode | HEAD moves | Staging area | Working directory |
|---|---|---|---|
--soft |
back | unchanged (still staged) | unchanged |
--mixed (default) |
back | cleared | unchanged |
--hard |
back | cleared | reverted — changes lost |
###Practical decision guide
1
2
3
"I committed too early, want to add more changes" --soft
"I committed the wrong things, want to re-sort them" --mixed
"This entire commit was a mistake, delete everything" --hard
##Mistake 3: Modified a File and Want to Discard Changes
The situation: You edited a file, realized it was all wrong, and want to throw away your local edits and get the last committed version back.
1
2
3
4
5
6
7
8
9
10
11
12
13
echo "good content" > app.py
git add app.py
git commit -m "add good content"
#Now make a mess
echo "terrible mistake" > app.py
cat app.py
#terrible mistake
#Discard the edit, restore to last committed version
git restore app.py
cat app.py
#good content
Warning:
git restore <file>throws away your uncommitted changes with no way to recover them. Only do this if you are sure.
##Mistake 4: Want to Edit the Last Commit Message
You just committed but the message has a typo or is unclear:
1
2
3
4
5
6
7
git commit -m "Add login funtionality" #typo!
#Fix the message (before pushing)
git commit --amend -m "Add login functionality"
git log --oneline
#Shows the corrected message
You can also add a forgotten file to the last commit:
1
2
git add forgotten_file.py
git commit --amend --no-edit #keep the same message, just add the file
Only use
--amendon commits you have NOT pushed yet. Amending a pushed commit causes problems for teammates.
##Mistake 5: How to See What Changed (git log + git diff)
Before fixing any mistake, understand what happened first:
1
2
3
4
5
6
7
8
9
10
11
#See recent commits
git log --oneline -5
#See exactly what a specific commit changed
git show a4b5c6d
#Compare two commits
git diff a4b5c6d f1a2b3c
#See what changed in the last commit
git diff HEAD~1 HEAD
##Safety Rules
| Rule | Why |
|---|---|
| Commit often | The more commits you have, the easier it is to pinpoint and undo a mistake |
Never use --hard without checking git log first |
Know what you are about to delete |
Never --amend or reset pushed commits |
It rewrites history and breaks your teammates’ clones |
Add .gitignore before your first commit |
Secrets and logs committed once are hard to fully erase |
When in doubt, git status |
It always tells you what state you are in |
##Quick Reference
| Situation | Command |
|---|---|
| Unstage a file | git restore --staged <file> |
| Unstage everything | git restore --staged . |
| Discard file edits | git restore <file> |
| Undo last commit, keep staged | git reset --soft HEAD~1 |
| Undo last commit, unstage too | git reset --mixed HEAD~1 |
| Undo last commit, delete changes | git reset --hard HEAD~1 |
| Fix last commit message | git commit --amend -m "new message" |
| Add forgotten file to last commit | git add file && git commit --amend --no-edit |
Next: 05-remote-collaboration.md — Push your work and collaborate with a team