Git gives you many ways to undo mistakes. The right tool depends on where the mistake is.
Mistake is in... Use...
─────────────────────────────────────────
Working directory git checkout -- <file> or git restore <file>
Staging area git reset HEAD <file> or git restore --staged <file>
Last commit (not pushed) git commit --amend
Older commit (not pushed) git rebase -i
Any commit (already pushed) git revert
echo "BROKEN CODE" > index.js
git statusChanges not staged for commit:
modified: index.js
git restore index.js
cat index.jsconsole.log('hello');
function greet() { return 'hi'; }
🧠 What happened? git restore replaced the working directory version with the version from the staging area (which matches the last commit). Your changes are gone — this is not reversible.
echo "secret=abc123" > .env
git add .env # Oops, didn't mean to stage this
git restore --staged .env
git statusUntracked files:
.env
🧠 What happened? The file is still on disk, but it's no longer staged for commit. Your changes are safe.
git commit --amend -m "Add greet function to index.js"echo "test" > test.js
git add test.js
git commit --amend --no-edit🧠 What happened? --amend replaces the last commit with a new one. The old commit is discarded. Never amend commits you've already pushed — it rewrites history.
git log --onelinec3d4e5f Add broken feature
e4f5a6b Add greet function
a1b2c3d Initial commit
git revert c3d4e5f[main f6g7h8i] Revert "Add broken feature"
1 file changed, 1 deletion(-)
git log --onelinef6g7h8i Revert "Add broken feature"
c3d4e5f Add broken feature
e4f5a6b Add greet function
a1b2c3d Initial commit
🧠 What happened? git revert creates a new commit that undoes the changes from the target commit. History is preserved. This is the safe way to undo public commits.
Reset is powerful and comes in three flavors:
Moves HEAD? Resets Index? Resets Working Dir?
git reset --soft ✅ ❌ ❌
git reset --mixed ✅ ✅ ❌
git reset --hard ✅ ✅ ✅
git reset --soft HEAD~1
git statusChanges to be committed:
modified: index.js
🧠 What happened? The commit is gone, but your changes are still staged. Useful when you want to re-do a commit.
git reset HEAD~1
git statusChanges not staged for commit:
modified: index.js
git reset --hard HEAD~1--hard permanently discards uncommitted changes. Use with extreme care.
git reset --hard a1b2c3d🧠 What happened? Your branch now points to a1b2c3d. All commits after it are orphaned (but recoverable via git reflog for ~30 days).
git clean -nWould remove temp.txt
Would remove debug.log
git clean -fgit clean -fd