Git Undoing Changes — Complete Safety Net Guide
Git gives you multiple ways to undo mistakes at every stage — from discarding uncommitted changes in your working directory to recovering lost commits weeks later — because every developer makes errors and needs a reliable safety net.
What You’ll Learn
By the end of this tutorial, you’ll undo changes at every stage: working directory, staging area, local commits, and pushed commits. You’ll master git restore, git reset, git revert, git stash, and git reflog — the five tools every Git user needs for damage control.
Why Undoing Changes Matters
Knowing how to undo mistakes isn’t just about fixing errors — it’s the confidence to experiment. When you know you can always revert, you try bolder refactors, test risky changes, and explore without fear. DodaTech’s engineering team treats undo workflows as a core skill: every developer must know how to recover from mistakes before shipping code to production.
Security note: Understanding Git Undo helps build more secure applications — a core principle at DodaTech, where tools like Durga Antivirus Pro and Doda Browser rely on solid implementation practices.
Undoing Changes Learning Path
flowchart LR
A[Git Basics] --> B[Branching & Merging]
B --> C[Remote Repositories]
C --> D[Undoing Changes]
D --> E[Advanced Git]
style D fill:#3b82f6,stroke:#fff,color:#fff
git add, git commit, and git push. Review Git and Git first.Undo Decision Tree
Before any undo operation, ask: “Where is the change I want to undo?”
flowchart TD
A[What do you want to undo?] --> B[Unstaged changes]
A --> C[Staged changes]
A --> D[Last commit locally]
A --> E[Pushed commit]
A --> F[Lost commits]
B --> G[git restore file]
C --> H[git restore --staged file]
D --> I{Keep changes?}
I -->|Yes| J[git reset --soft HEAD~1]
I -->|No| K[git reset --hard HEAD~1]
E --> L[git revert COMMIT]
F --> M[git reflog → git reset]
Analogy: Think of Git’s stages like kitchen prep. Unstaged = ingredients on the counter (easily put back). Staged = ingredients in the mixing bowl (can be removed without cooking). Committed = baked cake (harder to undo, but possible). Pushed = cake served to guests (must add a new cake, not destroy the old one).
Discard Unstaged Changes
Changes you made but haven’t git add-ed yet:
# Discard a single file — revert to last committed version
git restore index.html
# Discard all unstaged changes
git restore .
# Older syntax (still works everywhere)
git checkout -- index.htmlWhat’s happening: You’re telling Git “forget my edits, give me the version from the last commit.” The changes are gone — unrecoverable — so use git diff first to confirm.
Unstage a File
You ran git add but changed your mind — remove from staging but keep your edits:
git restore --staged index.html # newer syntax (Git 2.23+)
git reset HEAD index.html # older syntax (still very common)Analogy: You put items in your shopping cart but decided not to buy them. The items stay in your hands (working directory) — they just leave the cart (staging area).
Amend the Last Commit
Fix the commit message or add forgotten files to the most recent commit:
# Change message only
git commit --amend -m "Better commit message"
# Add forgotten files
git add forgotten-file.js
git commit --amend --no-edit # keep existing message
# Combine both
git add . && git commit --amend -m "New message"Why this works: Instead of creating a new commit, --amend replaces the last commit with a new one that has the same parent. The old commit is gone (but still in reflog).
Undo a Local Commit — Reset
Moves the branch pointer backward, undoing commits:
# Soft — moves HEAD back, keeps changes staged (ready to recommit)
git reset --soft HEAD~1
# Mixed (default) — moves HEAD back, unstages changes
git reset HEAD~1
# Hard — discards changes entirely ⚠️ DANGEROUS
git reset --hard HEAD~1Mode comparison:
| Mode | HEAD moves? | Staging cleared? | Changes preserved? |
|---|---|---|---|
--soft | Yes | No | Yes (staged) |
--mixed | Yes | Yes | Yes (unstaged) |
--hard | Yes | Yes | No |
git reset --hard permanently deletes uncommitted changes in your working directory. Once gone, they cannot be recovered (unless found in reflog). Always check git status and git diff before running --hard.Analogy: git reset is like time travel. --soft takes you back but keeps your luggage packed. --mixed takes you back and unpacks everything. --hard takes you back and burns the suitcase.
Revert a Commit — Safe for Shared History
git revert creates a new commit that undoes a previous one — it doesn’t rewrite history:
# Revert the last commit
git revert HEAD
# Revert a specific commit
git revert a1b2c3d
# Revert a range (newest first — Git processes oldest first)
git revert a1b2c3d..d4e5f6g
# Revert without auto-committing (inspect changes first)
git revert --no-commit a1b2c3dWhy revert is safe: It adds new history instead of rewriting it. If your team already pulled the bad commit, git revert gives them a clean undo without conflicts. This is the only safe way to undo pushed commits on shared branches.
Stashing — Temporary Parking
Stash saves uncommitted work so you can switch contexts:
# Save changes (tracked files only)
git stash
# Save with a message
git stash push -m "WIP: fixing header animation"
# Include untracked files
git stash -u
# List stashes
git stash list
# stash@{0}: On feature-navbar: WIP: fixing header animation
# Apply the latest stash (keeps it in list)
git stash apply
# Apply and remove from list
git stash pop
# Apply a specific stash
git stash apply stash@{2}
# Create a branch from a stash
git stash branch new-feature stash@{0}
# Clear all stashes
git stash clearTypical stash workflow — urgent bug fix:
git stash push -m "WIP: feature in progress" # save current work
git checkout main # switch to main
git checkout -b fix-urgent-bug # fix the bug
# ... fix bug, commit, push, PR ...
git checkout feature-navbar # back to feature
git stash pop # restore saved workAnalogy: Stashing is like putting a bookmark in your current page, closing the book, reading another book, then opening back to your bookmark.
Reflog — Recover the Unrecoverable
The reflog records every HEAD movement for ~90 days:
# View reflog
git reflog
# a1b2c3d HEAD@{0}: commit: Add dark mode
# d4e5f6g HEAD@{1}: commit: Fix header
# 7a8b9c0 HEAD@{2}: reset: moving to HEAD~1
# Recover a "lost" commit after reset --hard
git reset --hard a1b2c3d
# Or create a branch at the lost commit (safer)
git branch recovered-feature a1b2c3dWhy reflog exists: Even git reset --hard can’t destroy commits immediately. As long as Git hasn’t garbage-collected (usually 90 days), the commit data exists. Reflog is your safety net’s safety net.
Reset vs Revert vs Restore
| Command | Scope | Rewrites history? | Safe for pushed? |
|---|---|---|---|
git reset | Local commits | Yes | No |
git revert | Any commit | No | Yes |
git restore | Working tree / staging | N/A | Yes |
git commit --amend | Last commit | Yes | No (unless forced) |
Common Mistakes
1. Using git reset --hard when you meant --soft
--hard destroys uncommitted work permanently. Always check git status first. Unless you’re absolutely certain, use --soft or --mixed — they preserve your changes.
2. Amending a commit that’s already been pushed
Amending rewrites the commit hash. Anyone who pulled the original will see duplicate commits or merge conflicts. Only amend unpushed commits.
3. Confusing git revert with git reset
git revert creates a new commit that undoes the old one — safe for shared branches. git reset rewrites history — safe only for local, unpushed commits.
4. Forgetting to stash untracked files
By default git stash only saves tracked files. Use git stash -u to include untracked files, or git stash -a to include everything (including ignored files).
5. Not checking the reflog before panicking
After git reset --hard or a mistaken branch delete, check git reflog. If the commit is less than 90 days old and hasn’t been garbage-collected, you can recover it.
6. Using stash when you should have committed
Stashes are temporary and easy to forget — especially stash@{3} from two weeks ago. If the work is significant, commit it to a temporary branch: git checkout -b wip-feature.
Practice Questions
1. What is the difference between git reset --hard HEAD~1 and git revert HEAD?
Answer: reset --hard removes the last commit entirely (rewrites history, dangerous for shared branches). revert creates a new commit that undoes the last one (safe for all branches).
2. When should you use git stash instead of committing?
Answer: When you need to temporarily set aside unfinished work to handle an urgent task. Stash for short-term parking; commit for anything you might reference later.
3. How do you recover a commit after accidentally running git reset --hard?
Answer: Run git reflog to find the commit hash before the reset, then git reset --hard <hash> or git branch recover <hash>.
4. What does git restore --staged do?
Answer: It unstages a file (removes it from the staging area) while keeping all your changes in the working directory.
Challenge
Create a new repo, make three commits, then use interactive rebase to squash the last two into one. Then use git reflog to find the original commits and recover them.
FAQ
Try It Yourself
Create a scenario and practice every undo operation:
# 1. Setup
mkdir undo-practice && cd undo-practice
git init
echo "line 1" > file.txt && git add . && git commit -m "First commit"
echo "line 2" >> file.txt && git add . && git commit -m "Second commit"
echo "line 3" >> file.txt
# 2. Discard unstaged changes
git restore file.txt
cat file.txt # line 3 is gone
# 3. Unstage a staged change
echo "line 3" >> file.txt && git add file.txt
git restore --staged file.txt
# 4. Amend last commit
git add . && git commit -m "Bad message"
git commit --amend -m "Add line 3 to file"
# 5. Reset (soft)
git reset --soft HEAD~1 # undo, keep changes staged
git reset HEAD~1 # undo, unstage
git add . && git commit -m "Restored commit"
# 6. Stash
echo "line 4" >> file.txt
git stash push -m "WIP: line 4"
git stash pop
# 7. Revert
git log --oneline
git revert HEAD # creates new commit undoing lastWhat’s Next
Advance to Git power user features:
| Topic | Description |
|---|---|
| https://tutorials.dodatech.com/devops/git/git-advanced/ | Tags, hooks, submodules, signing |
| https://tutorials.dodatech.com/devops/git/git-reference/ | Quick command cheatsheet |
Related topics to explore:
- Git Overview
- DevOps Practices
- JavaScript Projects
What’s Next
Congratulations on completing this Git Undo tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro