Everyone makes mistakesβit's part of development. The key is knowing how to fix them. Git provides powerful tools to undo changes at every stage of your workflow, from discarding uncommitted edits to safely reversing published commits. In this lesson, you'll learn the difference between git restore, git reset, and git revert, understand when to use each one, and gain the confidence to fix mistakes without fear of losing work.
Understanding "Undo" in Git
Git has multiple commands for undoing changes, each designed for different scenarios:
- git restore: Discard changes in working directory or unstage files
- git reset: Move branch pointer to a different commit (rewrite history)
- git revert: Create a new commit that undoes a previous commit (preserve history)
The command you choose depends on what you want to undo and whether you've shared your changes.
π― The Golden Rule
Never rewrite history that has been pushed to a shared repository.
If others have your commits, use git revert (safe). If commits are only local, you can use git reset (rewrites history).
Which Undo Command Should I Use?
Here's a decision tree to help you choose:
What do you want to undo?
ββ Uncommitted changes to a file
β ββ Use: git restore filename
β
ββ Staged changes (unstage but keep edits)
β ββ Use: git restore --staged filename
β
ββ Last commit (not pushed)
β ββ Keep changes staged
β β ββ Use: git reset --soft HEAD~1
β ββ Keep changes unstaged
β β ββ Use: git reset HEAD~1 (or --mixed)
β ββ Discard changes completely
β ββ Use: git reset --hard HEAD~1
β
ββ Commit that's been pushed
ββ Use: git revert commit-hashGit Restore: Discarding Changes
git restore is the modern, clear way to discard changes or unstage files. It was introduced in Git 2.23 to split the confusinggit checkout command into separate, clear commands.
Discard Uncommitted Changes
Throw away changes in your working directory:
# Discard changes to a specific file
git restore filename.txt
# Discard changes to multiple files
git restore file1.txt file2.txt
# Discard all changes in current directory
git restore .Warning: This permanently deletes your uncommitted changes! They cannot be recovered. Make sure you really want to discard them.
Example: Discard Unwanted Changes
# You edited index.html but don't like the changes
git status
# modified: index.html
# Discard the changes
git restore index.html
# File is back to last committed version
git status
# nothing to commit, working tree cleanUnstage Files
Remove files from staging area without discarding changes:
# Unstage a specific file
git restore --staged filename.txt
# Unstage all files
git restore --staged .Example: Unstage Accidentally Staged Files
# You staged everything, including debug files
git add .
# Check what's staged
git status
# Changes to be committed:
# modified: app.js
# modified: debug.js β Don't want this
# Unstage just the debug file
git restore --staged debug.js
# Now debug.js is modified but not staged
git status
# Changes to be committed:
# modified: app.js
# Changes not staged for commit:
# modified: debug.jsRestore a File from a Specific Commit
# Restore a file to how it was in a specific commit
git restore --source=a1b2c3d filename.txt
# Restore a file from 3 commits ago
git restore --source=HEAD~3 filename.txtGit Reset: Moving the Branch Pointer
git reset moves your current branch pointer to a different commit. This effectively "undoes" commits by making your branch point to an earlier state.
Important: git reset rewrites history. Only use it on commits that haven't been pushed!
The Three Types of Reset
1. Soft Reset (--soft)
Moves HEAD but keeps all changes staged:
git reset --soft HEAD~1What it does:
- β Moves branch pointer back one commit
- β Keeps all changes in staging area
- β Keeps working directory unchanged
Use case: You want to redo the last commit with a different message or add more changes to it.
# Made a commit with a typo in the message
git commit -m "Add usr authentication" # Oops, "usr" should be "user"
# Undo the commit but keep changes staged
git reset --soft HEAD~1
# Fix the message
git commit -m "Add user authentication"2. Mixed Reset (--mixed, default)
Moves HEAD and unstages changes (but keeps them in working directory):
git reset HEAD~1
# or explicitly:
git reset --mixed HEAD~1What it does:
- β Moves branch pointer back one commit
- β Unstages changes (removes from staging area)
- β Keeps changes in working directory
Use case: You want to undo a commit and rethink what to stage.
# Committed too many files together
git commit -m "Multiple changes"
# Undo commit, keep changes unstaged
git reset HEAD~1
# Now selectively stage and commit separately
git add feature.js
git commit -m "Add new feature"
git add bugfix.js
git commit -m "Fix bug in login"3. Hard Reset (--hard)
Moves HEAD and discards all changes:
git reset --hard HEAD~1What it does:
- β Moves branch pointer back one commit
- β Discards staged changes
- β Discards working directory changes
DANGER: git reset --hard permanently deletes uncommitted work! Only use it when you're absolutely sure you want to discard everything.
Use case: You want to completely abandon recent work and start fresh.
# You went down the wrong path
git log --oneline
# a1b2c3d (HEAD -> main) Wrong approach
# f4e5d6c Another mistake
# c7d8e9f This was good β Want to go back here
# Completely reset to c7d8e9f
git reset --hard c7d8e9f
# Everything after c7d8e9f is goneReset Comparison
Starting point: You have a commit you want to undo
Working Dir Staging Area Repository
--soft Keep Keep Change
--mixed Keep Clear Change
--hard Clear Clear Changeπ‘ Remember the Reset Types
Think of it as levels of "forgetfulness":
- --soft: Git forgets the commit, remembers everything else
- --mixed: Git forgets the commit and staging, remembers your edits
- --hard: Git forgets everything (commit, staging, edits)
Git Revert: Safe History Preservation
git revert creates a new commit that undoes changes from a previous commit. Unlike git reset, it doesn't rewrite historyβit adds to it.
How Revert Works
Before revert:
A --- B --- C --- D (main)
After reverting commit C:
A --- B --- C --- D --- E (main)
β
(reverts C's changes)Commit E is a new commit that undoes everything commit C did. If C added lines, E removes them. If C deleted lines, E adds them back.
Basic Revert
# Revert the last commit
git revert HEAD
# Revert a specific commit
git revert a1b2c3d
# Revert multiple commits
git revert HEAD~3..HEADExample: Revert a Pushed Commit
# You pushed a bug to production
git log --oneline
# a1b2c3d (HEAD -> main, origin/main) Add new feature (BUG!)
# f4e5d6c Previous commit
# c7d8e9f Earlier commit
# Can't use reset because others have this commit
# Use revert instead
git revert a1b2c3d
# Git opens editor for revert commit message:
# "Revert 'Add new feature'"
# Save and close
# New commit created that undoes the bug
git log --oneline
# b0a1c2d (HEAD -> main) Revert "Add new feature"
# a1b2c3d (origin/main) Add new feature (BUG!)
# f4e5d6c Previous commit
# Push the revert
git push
# The bug is now undone, history is preservedRevert Without Opening Editor
# Use --no-edit to skip editing the message
git revert HEAD --no-edit
# Or provide a custom message
git revert a1b2c3d -m "Revert feature X due to bug"Revert and Continue Editing
# Start revert but don't commit yet
git revert a1b2c3d --no-commit
# Make additional changes if needed
# Then commit when ready
git commit -m "Revert feature X and update docs"When to Use Revert vs Reset
Use git revert when:
- The commit has been pushed to a shared repository
- Other people might have the commit
- You want to preserve complete history
- You're working on a public/shared branch
Use git reset when:
- The commit exists only on your local machine
- You haven't pushed yet
- You're working on a private branch
- You want a cleaner history
Practical Undo Scenarios
Scenario 1: Fix a Bad Commit Message
# Just committed with wrong message
git commit -m "Fix bg" # Oops, meant "bug"
# Amend the commit message
git commit --amend -m "Fix bug in login validation"
# Or open editor to write better message
git commit --amendScenario 2: Forgot to Add Files to Commit
# Made a commit but forgot a file
git commit -m "Add user profile page"
# Oops, forgot profile.css
git add profile.css
# Add to the previous commit
git commit --amend --no-edit
# The forgotten file is now part of the last commitScenario 3: Committed to Wrong Branch
# You're on main but should be on feature branch
git log --oneline
# a1b2c3d (HEAD -> main) New feature (WRONG BRANCH!)
# Create feature branch pointing to current commit
git branch feature/new-feature
# Reset main to before the commit
git reset --hard HEAD~1
# Switch to the feature branch
git switch feature/new-feature
# Commit is now on the right branch!Scenario 4: Undo Multiple Commits
# You want to undo the last 3 commits
git log --oneline
# a1b2c3d (HEAD -> main) Third commit
# f4e5d6c Second commit
# c7d8e9f First commit
# b0a1c2d Good commit β Want to go back here
# Option 1: Reset (if not pushed)
git reset --soft HEAD~3
# All 3 commits undone, changes still staged
# Option 2: Reset and discard
git reset --hard HEAD~3
# All 3 commits and changes discarded
# Option 3: Revert (if pushed)
git revert HEAD~2..HEAD
# Creates 3 new commits that undo the changesScenario 5: Recover Deleted Files
# Accidentally deleted a file
rm important.txt
# Restore it from last commit
git restore important.txt
# Or if you committed the deletion
git log --oneline -- important.txt
# Find the last commit where it existed: f4e5d6c
# Restore from that commit
git restore --source=f4e5d6c important.txtScenario 6: Undo Staged Changes
# Staged too many files
git add .
# Unstage specific file
git restore --staged debug.js
# Or unstage everything
git restore --staged .Recovering "Lost" Commits
Even after resetting or losing commits, Git keeps them for a while. You can recover them using git reflog.
What is Reflog?
The reflog (reference log) records every time HEAD movesβevery commit, reset, checkout, etc. It's like an undo history for Git itself.
# View reflog
git refloga1b2c3d HEAD@{0}: reset: moving to HEAD~3
f4e5d6c HEAD@{1}: commit: Third commit
c7d8e9f HEAD@{2}: commit: Second commit
b0a1c2d HEAD@{3}: commit: First commitRecover a Reset Commit
# You did a hard reset and regret it
git reset --hard HEAD~3
# Oh no! Want those commits back
# Check reflog
git reflog
# Find the commit before the reset
# f4e5d6c HEAD@{1}: commit: Third commit
# Reset to that commit
git reset --hard f4e5d6c
# Your commits are back!π Git Keeps Everything
Git keeps "lost" commits for about 30 days (90 days for referenced commits). During this time, you can usually recover them using reflog!
Traditional Commands (Still Widely Used)
Before git restore (Git 2.23), people used git checkout and git reset for these operations. You'll still see these in tutorials and scripts:
Old vs New Commands
# Discard changes to a file
git checkout -- filename # Old way
git restore filename # New way
# Unstage a file
git reset HEAD filename # Old way
git restore --staged filename # New way
# Switch branches
git checkout branch-name # Old way
git switch branch-name # New wayBoth work, but the new commands are clearer about what they do.
Practice Undo Commands
Try these commands to practice undoing changes safely:
Practice Undoing Changes
Experiment with restore, reset, and viewing history
Try these examples:
Safety Tips for Undoing Changes
1. Always Check Status First
# Before any undo operation
git status
git log --oneline -5
# Know what state you're in!2. Use Soft Reset When Unsure
If you're not sure, use --soft first. You can always go harder later:
# Safe: keeps everything
git reset --soft HEAD~1
# Check if this is what you want
git status
# If yes, commit again
# If no, continue with --mixed or --hard3. Create a Backup Branch
# Before risky operations, create a backup
git branch backup-before-reset
# Do your reset
git reset --hard HEAD~5
# Oops, that was wrong?
git reset --hard backup-before-reset
# Crisis averted!4. Use Revert for Published Commits
Never reset commits that have been pushed!
Use git revert instead. Resetting shared history causes major problems for collaborators.
5. Understand What You're Undoing
# Before resetting, see what you're about to undo
git show HEAD
git diff HEAD~3..HEAD
# Make sure you understand what will be lostCommand Reference
Here's a quick reference of all undo commands:
# Discard Changes (Working Directory)
git restore filename # Discard changes to file
git restore . # Discard all changes
git restore --source=abc123 file # Restore from specific commit
# Unstage Changes (Staging Area)
git restore --staged filename # Unstage specific file
git restore --staged . # Unstage all files
# Amend Last Commit
git commit --amend # Change last commit message
git commit --amend --no-edit # Add files to last commit
# Reset (Move Branch Pointer)
git reset --soft HEAD~1 # Undo commit, keep staged
git reset HEAD~1 # Undo commit, keep unstaged
git reset --hard HEAD~1 # Undo commit, discard changes
git reset --hard abc123 # Reset to specific commit
# Revert (Create New Commit)
git revert HEAD # Revert last commit
git revert abc123 # Revert specific commit
git revert HEAD~3..HEAD # Revert multiple commits
git revert abc123 --no-commit # Revert but don't commit yet
# Recovery
git reflog # View HEAD movement history
git reset --hard abc123 # Recover "lost" commit
# Traditional Commands (Still Work)
git checkout -- filename # Old: discard changes
git reset HEAD filename # Old: unstage file
git checkout branch # Old: switch branchKey Takeaways
git restorediscards changes or unstages filesgit resetmoves branch pointer and rewrites history (local only!)git revertcreates new commits to undo previous ones (safe for shared history)--softkeeps changes staged,--mixedunstages them,--harddiscards them- Never reset commits that have been pushed to shared repositories
git reflogcan recover "lost" commits for ~30 daysgit commit --amendfixes the most recent commit- Always check status before undoing operations
- Create backup branches before risky operations
- When in doubt, use the safest option first (
--softorrevert)
What's Next?
Congratulations! You've completed the Core Git Concepts section. You now understand commits, branches, merging, the staging area, and how to undo changes. These are the fundamental skills that every Git user needs.
In the next section, we'll start Working with GitHub. You'll learn how to connect your local Git repositories to GitHub, push and pull code, collaborate with others, and use GitHub's powerful features. This is where your local Git knowledge meets the world of collaborative development!
π― Practice Assignment
Before moving to GitHub, practice undoing changes:
- Make several commits in a test repository
- Practice using
git reset --soft,--mixed, and--hard - Try reverting a commit with
git revert - Intentionally "lose" a commit and recover it with
git reflog - Practice amending commits with
git commit --amend - Use
git restoreto discard changes and unstage files
The more comfortable you are fixing mistakes, the more confident you'll be using Git!