Git & GitHub

Undoing Changes

13 min Lesson 8 of 35

Undoing Changes

Mistakes happen, and Git provides powerful tools to undo changes safely. In this lesson, you'll learn when and how to use different undo commands, from simple file restoration to complex history rewriting.

Understanding Undo Operations

Git offers different undo commands for different scenarios:

Git Restore: Undo changes in working directory and staging area Git Reset: Move branch pointer and optionally change staging/working Git Revert: Create new commit that undoes previous commit Git Clean: Remove untracked files and directories
Key Principle: Use git restore and git revert for safe operations. Use git reset carefully, especially with --hard. Never rewrite history that's been pushed to a shared repository.

Git Restore - Modern Way to Undo

Git restore (introduced in Git 2.23) is the safest way to undo changes:

# Discard changes in working directory (restore from staging) git restore filename.txt # Restore multiple files git restore file1.txt file2.txt # Restore all files in directory git restore . # Unstage a file (remove from staging area) git restore --staged filename.txt # Restore from a specific commit git restore --source=HEAD~2 filename.txt # Restore and unstage simultaneously git restore --staged --worktree filename.txt
Warning: git restore without --staged permanently discards uncommitted changes in your working directory. Make sure you really want to lose those changes!

Unstaging Files

Remove files from the staging area without losing changes:

# Unstage a specific file (Git 2.23+) git restore --staged filename.txt # Unstage all files git restore --staged . # Older method (still works) git reset HEAD filename.txt # Unstage and keep working directory changes git reset HEAD

Git Reset - Moving the Branch Pointer

Git reset has three modes with different levels of destructiveness:

--soft: Move HEAD, keep staging and working directory --mixed (default): Move HEAD, reset staging, keep working directory --hard: Move HEAD, reset staging AND working directory # Reset to previous commit (keep changes staged) git reset --soft HEAD~1 # Reset to previous commit (unstage changes, keep in working directory) git reset --mixed HEAD~1 git reset HEAD~1 # Same as above (--mixed is default) # Reset to previous commit (DISCARD ALL CHANGES) git reset --hard HEAD~1 # Reset to specific commit git reset --hard abc123 # Reset to remote branch state git reset --hard origin/main
Mnemonic: Think of reset modes as levels of "undoing": --soft = undo commit only, --mixed = undo commit + unstage, --hard = undo everything (nuclear option).

Practical Reset Examples

Common scenarios for using git reset:

# Scenario 1: Undo last commit but keep changes git reset --soft HEAD~1 # Edit files, then recommit with better message # Scenario 2: Completely remove last 3 commits git reset --hard HEAD~3 # Scenario 3: Unstage all files git reset # Scenario 4: Discard all local changes and match remote git fetch origin git reset --hard origin/main # Scenario 5: Undo to specific commit by hash git reset --hard 2f8a7e9
Critical Warning: git reset --hard permanently deletes uncommitted changes. There's no undo! Only use it when you're absolutely sure you want to discard all work.

Git Revert - Safe Public Undo

Revert creates a new commit that undoes a previous commit - safe for shared history:

# Revert the last commit git revert HEAD # Revert a specific commit git revert abc123 # Revert without creating commit immediately (stage changes) git revert --no-commit abc123 # Revert a range of commits git revert HEAD~3..HEAD # Revert multiple specific commits git revert abc123 def456 ghi789 # Abort a revert in progress git revert --abort # Continue after resolving conflicts git revert --continue

Reset vs Revert - When to Use Which

Use git reset when: ✓ Working on private/local branches ✓ Commits haven't been pushed yet ✓ You want to rewrite history ✓ Cleaning up before pushing Use git revert when: ✓ Working on shared/public branches ✓ Commits have been pushed ✓ You want to preserve history ✓ Undoing specific commits in the middle of history ✓ Working on main/master branch Example Decision: - Local feature branch with bad commit → Use reset - Production branch with bug → Use revert
Best Practice: If you're unsure, use git revert. It's always safe because it doesn't rewrite history. You can always clean up later with interactive rebase if needed.

Git Clean - Removing Untracked Files

Remove files that aren't tracked by Git:

# Preview what would be deleted (dry run) git clean -n # Remove untracked files git clean -f # Remove untracked files and directories git clean -fd # Remove ignored files too (.gitignore patterns) git clean -fx # Interactive mode (choose what to delete) git clean -i # Clean everything (files, directories, ignored) git clean -fdx
Warning: git clean permanently deletes untracked files. Always use -n (dry run) first to preview what will be deleted!

Recovering from Mistakes

Git keeps a reflog of all HEAD movements - your safety net:

# View reflog (history of HEAD changes) git reflog # Typical reflog output: # abc123 HEAD@{0}: reset: moving to HEAD~1 # def456 HEAD@{1}: commit: Add feature # ghi789 HEAD@{2}: commit: Fix bug # Recover after accidental reset git reset --hard HEAD@{1} # Recover after accidental branch deletion git checkout -b recovered-branch HEAD@{1} # View reflog for specific branch git reflog show feature-branch # Reflog entries expire after 90 days by default git reflog expire --expire=now --all # Clear reflog

Practical Recovery Scenarios

# Scenario 1: Accidentally deleted a branch git reflog # Find the commit hash git checkout -b recovered-branch abc123 # Scenario 2: Reset too far back git reflog # Find where you were git reset --hard HEAD@{2} # Scenario 3: Lost commits after hard reset git reflog git cherry-pick abc123 # Recover specific commit # Scenario 4: Undo the undo git reflog git reset --hard HEAD@{1}
Pro Tip: Before doing any potentially destructive operation, create a backup branch: git branch backup. If something goes wrong, you can always git reset --hard backup to get back.

Undoing Specific File Changes

Undo changes to specific files at different stages:

# Discard working directory changes for one file git restore filename.txt # Restore file from specific commit git restore --source=HEAD~3 filename.txt # Restore file from another branch git restore --source=feature-branch filename.txt # Restore file and stage it git restore --source=HEAD~1 --staged --worktree filename.txt # Revert changes to a file in last commit git show HEAD:filename.txt > filename.txt git add filename.txt git commit -m "Revert filename.txt to previous state"

Amend Last Commit

Fix mistakes in the most recent commit:

# Change commit message only git commit --amend -m "Better commit message" # Add forgotten files to last commit git add forgotten-file.txt git commit --amend --no-edit # Change last commit completely git add modified-file.txt git commit --amend # Amend author information git commit --amend --author="Name <email@example.com>"

Practice Exercise:

Scenario: You've made several mistakes and need to fix them:

  1. Modified config.txt but want to discard changes
  2. Staged temp.txt by mistake and need to unstage it
  3. Last commit has a typo in the message
  4. Two commits ago, you committed something wrong (already pushed)

Solutions:

# 1. Discard changes to config.txt git restore config.txt # 2. Unstage temp.txt git restore --staged temp.txt # 3. Fix commit message (if not pushed yet) git commit --amend -m "Corrected commit message" # 4. Revert old commit (safe for pushed commits) git log --oneline # Find the commit hash git revert abc123 # Revert the bad commit

Best Practices for Undoing Changes

✓ DO: - Use git restore for working directory changes - Use git revert for shared/public branches - Always preview with -n before git clean - Check git reflog when something goes wrong - Create backup branches before risky operations - Prefer revert over reset for pushed commits ✗ DON'T: - Use git reset --hard on pushed commits - Use git clean without -n first - Rewrite public/shared history - Panic - reflog can save you - Force push without understanding consequences - Mix reset and revert strategies

Summary

In this lesson, you learned:

  • Using git restore to discard changes and unstage files
  • Three modes of git reset: soft, mixed, and hard
  • Using git revert for safe public history undoing
  • When to use reset vs revert
  • Removing untracked files with git clean
  • Recovering from mistakes using reflog
  • Amending the last commit
  • Best practices for safe undo operations
Next Up: In the next lesson, we'll explore branching in Git - one of its most powerful features for parallel development!

ES
Edrees Salih
15 hours ago

We are still cooking the magic in the way!