Undoing Changes in Git
Learn how to use restore, reset, revert, and clean safely, and understand the difference between undoing local work and undoing shared history.
Why Undoing Changes Feels Confusing
Git offers several ways to undo work, and beginners often mix them up because the commands affect different places:
- the working directory
- the staging area
- commit history
The good news is that each command has a clear purpose once you separate them.
Tip: Before undoing anything, run
git statusand ask yourself: am I trying to undo a file change, unstage something, move a branch pointer, or create a reverse commit?
git restore: Undo File-Level Changes
Use git restore when you want to discard changes in files or unstage them.
Discard unstaged changes in a file
git restore app.js
This replaces the working copy with the version from the index or the latest commit, depending on context.
Unstage a file
git restore --staged app.js
That removes the file from the staging area but keeps your actual file edits.
Practical Example
echo "debug=true" >> config.env
git add config.env
git restore --staged config.env
Now the change still exists in the file, but it is no longer staged for commit.
git reset: Move HEAD and Possibly More
git reset changes where the current branch points. Depending on the mode, it may also affect the staging area and working directory.
Soft Reset
git reset --soft HEAD~1
This moves the branch back one commit but keeps the changes staged.
Use it when the last commit message was wrong or you want to recommit differently.
Mixed Reset
git reset --mixed HEAD~1
This is the default reset mode. It moves the branch back and unstages the changes, but keeps them in your working directory.
Use it when you want to redo the commit more carefully.
Hard Reset
git reset --hard HEAD~1
This moves the branch back and discards staged and working directory changes to match the target commit.
Note: Hard reset is destructive. Use it only when you are sure you no longer need the discarded work.
git revert: Safely Undo a Commit in Shared History
git revert does not remove a commit. Instead, it creates a new commit that reverses the changes from an earlier commit.
git revert a1b2c3d
This is often the safest choice for undoing something that has already been pushed and shared with others.
Why Revert Is Safe for Teams
Because it adds a new commit instead of rewriting history, teammates do not have to deal with force pushes or changed commit IDs.
A common production fix looks like this:
git log --oneline
git revert 8d92a11
git push origin main
git clean: Remove Untracked Files
git clean deals with files Git is not tracking.
Preview what would be removed:
git clean -n
Delete untracked files:
git clean -f
Delete untracked files and directories:
git clean -fd
This is useful when build artifacts or temporary generated files clutter your working directory.
Tip: Always start with
git clean -nso you can see what Git plans to remove.
How the Commands Differ
Here is the simplest way to separate them:
| Command | Main purpose |
|---|---|
git restore | Discard file changes or unstage files |
git reset | Move branch history and optionally unstage or discard changes |
git revert | Create a new commit that undoes an earlier commit |
git clean | Remove untracked files and folders |
Real-World Scenarios
Scenario 1: You staged the wrong file
git restore --staged secrets.txt
Scenario 2: Your last local commit should be redone
git reset --mixed HEAD~1
Scenario 3: A bad commit is already on main
git revert <commit-id>
Scenario 4: Build output files are cluttering the repo
git clean -n
git clean -fd
A Good Safety Habit
Before using destructive options like reset --hard or clean -f, inspect the current state:
git status
git log --oneline -5
If you are unsure, make a backup branch first:
git branch backup-before-reset
That small step can save a lot of stress.
What You Should Remember
Undoing changes in Git is easier when you match the tool to the problem. Use restore for file-level undo, reset for local history changes, revert for safely undoing shared commits, and clean for removing untracked files. The biggest caution is with destructive commands like reset --hard and clean -f.
When in doubt, prefer the safer option and inspect first.
Test Your Understanding
Let's see how well you understood the concepts! These exercises will help reinforce what you just learned.
Exercise 1: Unstaging without losing edits
Scenario: You accidentally staged config.env, but you still want to keep the actual file change in your working directory.
Question: Which command from the tutorial does exactly that?
Exercise 1: Unstaging without losing edits
Choose the command that removes a file from the staging area while preserving its edits.
Exercise 2: Redoing the last local commit
Scenario: Your most recent commit should be redone more carefully, but you want the changes to remain in your working directory and no longer be staged.
Question: Which reset mode from the tutorial fits that goal?
Exercise 2: Redoing the last local commit
Identify the reset mode that moves HEAD back and unstages changes while keeping the file edits.
Exercise 3: Undoing shared history safely
Scenario: A bad commit is already on the shared main branch, and teammates may have pulled it.
Question: Which command is usually the safest choice according to the tutorial?
Exercise 3: Undoing shared history safely
Pick the safest command for undoing a pushed commit on a shared branch.