⏪ Undo & Revert
⚠️ Warning: This chapter involves some dangerous operations. Before you start learning, remember one iron rule: commits that have already been pushed to a remote repository should not be easily modified, or your teammates will want to "have a chat" with you.
git restore — Discard Working Directory Changes
# Scenario: You modified index.html but think you messed it up, want to go back to the last committed state
# First, see what changed
git diff index.html
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -4,5 +4,5 @@
<title>My First Website</title>
</head>
<body>
- <h1>Hello, Git!</h1>
+ <h1>I broke this title</h1>
</body>
# Discard changes to this file
git restore index.html
# Verify: changes are gone
git diff index.html
(empty output, meaning no differences)📝 Note:
git restoreis a new command added in Git 2.23+, more intuitive than the oldgit checkout -- <file>. This operation is irreversible — the modified content will be permanently lost (normally unrecoverable, though professional data recovery tools might help). Think before you act!
git restore --staged — Unstage from the Staging Area
# Scenario: You added style.css to the staging area but suddenly want to undo it
git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: style.css
# Unstage from staging area (file changes are preserved, just unstaged)
git restore --staged style.css
git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: style.cssSimple, right? git restore discards working directory changes, git restore --staged only unstages but preserves changes. Remember this distinction and you won't get confused.
git reset — Roll Back Commits (Three Modes)
git reset is a very powerful command with three different "strengths," like an eraser with three levels of hardness:
Soft Reset — Only Roll Back the Commit, Keep Staging Area and Working Directory
# Roll back one commit, but keep changes in the staging area
git reset --soft HEAD~1
# Use case: you wrote the wrong commit message and want to rewrite it
git reset --soft HEAD~1
git commit -m "fix: correct commit message"Mixed Reset (Default) — Roll Back Commit and Staging Area, Keep Working Directory
# Roll back one commit, staging area also cleared, but working directory changes preserved
git reset HEAD~1
# Same as
git reset --mixed HEAD~1
# Use case: want to reorganize which files should be in one commitHard Reset — Roll Back Everything, Changes Disappear!
# ⚠️ Dangerous! All uncommitted changes will be lost!
git reset --hard HEAD~1
HEAD is now at a1b2c3d feat: create homepage, Hello Git!⚠️ Warning: ⚠️
--hardis a nuclear-level operation! It completely discards all uncommitted changes and cannot be recovered withgit restore. Before using it, make sure you really don't need those changes anymore. If you just want to "point the branch to another commit," consider usinggit revertwhich is safer.
| Mode | Commit History | Staging Area | Working Directory |
|---|---|---|---|
| --soft | Rolled back ✗ | Preserved ✓ | Preserved ✓ |
| --mixed | Rolled back ✗ | Rolled back ✗ | Preserved ✓ |
| --hard | Rolled back ✗ | Rolled back ✗ | Rolled back ✗ |
git revert — Safely "Undo" a Commit
If git reset is time travel (modifying history), then git revert is writing a "recall email" — it doesn't modify history, but instead creates a new commit to "offset" the previous one.
# Revert the most recent commit
git revert HEAD
[main c3d4e5f] Revert "feat: add welcome message"
1 file changed, 1 insertion(+), 1 deletion(-)
# View history — note the revert commit is still there
git log --oneline
c3d4e5f (HEAD -> main) Revert "feat: add welcome message"
f4e5d6c feat: add welcome message
b2c3d4e feat: add base styles
a1b2c3d feat: create homepage, Hello Git!💡 Tip: For commits that have already been pushed to a remote, always use
git revertinstead ofgit reset. Because revert doesn't change history, your teammates won't be affected.
git reflog — The Last Lifeline
If Git is a time machine, then reflog is the time machine's operation log — it records every movement of the HEAD pointer.
# Scenario: You accidentally ran git reset --hard and deleted all your changes!
# Don't panic! Check reflog first
git reflog
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
f4e5d6c HEAD@{1}: commit: feat: add welcome message
b2c3d4e HEAD@{2}: commit: feat: add base styles
a1b2c3d HEAD@{3}: commit (initial): feat: create homepage, Hello Git!
# Find the commit you want to restore
# f4e5d6c is the "add welcome message" commit
# Restore to that state!
git reset --hard f4e5d6c
HEAD is now at f4e5d6c feat: add welcome message
# Changes are back!📝 Note: reflog keeps records for 90 days by default. Within those 90 days, almost any "accidental" operation can be recovered. This is Git's safety net.