Git Reset

Master Git reset to undo changes, unstage files, and manage your repository state effectively

Git Reset: Undoing Changes Safely

Git reset is a powerful command for undoing changes at different stages of your Git workflow. Unlike git revert which creates new commits, git reset actually moves the repository state backwards. This guide covers when and how to use reset effectively and safely.

Understanding Git Reset

git reset modifies three things in Git:

  1. HEAD pointer - where your current branch points
  2. Staging area (index) - files prepared for commit
  3. Working directory - your actual files

⚠️ Important: Reset can potentially lose work. Always understand what you're doing before using it!


The Three Types of Reset

1. Soft Reset (--soft)

What it does: Moves HEAD to specified commit, keeps staging area and working directory unchanged.

Use case: Undo commits but keep all changes staged for recommitting.

# Undo last commit, keep changes staged
git reset --soft HEAD~1

# Undo last 3 commits, keep all changes staged
git reset --soft HEAD~3

# Reset to specific commit
git reset --soft abc1234

Example workflow:

# Made several small commits, want to combine them
git log --oneline
# a1b2c3d Fix typo in README
# e4f5g6h Add more examples
# i7j8k9l Initial documentation
# m0n1o2p Previous stable commit

# Reset to combine last 3 commits
git reset --soft HEAD~3

# All changes are now staged, create single commit
git commit -m "Add comprehensive documentation with examples"

2. Mixed Reset (--mixed) - Default

What it does: Moves HEAD to specified commit, resets staging area, keeps working directory unchanged.

Use case: Undo commits and unstage changes, but keep files modified in working directory.

# Default behavior (--mixed is implicit)
git reset HEAD~1
git reset --mixed HEAD~1  # Same as above

# Unstage specific files
git reset HEAD file.txt
git reset file.txt  # Same as above

Example workflow:

# Accidentally committed too early, want to modify before recommitting
git reset HEAD~1  # Undo last commit
# Files are now modified but not staged

# Make additional changes
vim file.txt

# Stage and commit properly
git add .
git commit -m "Complete implementation with proper testing"

3. Hard Reset (--hard) ⚠️

What it does: Moves HEAD, resets staging area AND working directory. All changes are lost!

Use case: Completely discard commits and all changes since specified commit.

# DANGER: This will lose all uncommitted changes!
git reset --hard HEAD~1

# Reset to remote state (common after pull issues)
git reset --hard origin/main

# Reset to specific commit
git reset --hard abc1234

Safety check before hard reset:

# Check what you'll lose
git status
git diff
git diff --staged

# Create a backup branch first
git branch backup-$(date +%Y%m%d-%H%M)

# Now reset safely
git reset --hard HEAD~1

Common Use Cases

Unstaging Files

Unstage specific files:

# Unstage single file
git reset HEAD file.txt

# Unstage multiple files
git reset HEAD file1.txt file2.txt

# Unstage all files
git reset HEAD

Modern alternative:

# Git 2.23+ provides clearer commands
git restore --staged file.txt
git restore --staged .  # Unstage all

Fix Last Commit

Change commit message:

# Soft reset to edit commit message
git reset --soft HEAD~1
git commit -m "Better commit message"

# Or use amend (easier)
git commit --amend -m "Better commit message"

Add forgotten files:

# Reset to add more files to last commit
git reset --soft HEAD~1
git add forgotten-file.txt
git commit -m "Complete implementation"

# Or use amend
git add forgotten-file.txt
git commit --amend --no-edit

Undo Multiple Commits

# Undo last 3 commits, keep changes for reworking
git reset --mixed HEAD~3

# Completely remove last 3 commits and all changes
git reset --hard HEAD~3

# Reset to specific commit
git log --oneline  # Find commit hash
git reset --hard abc1234

Reset to Remote State

# Your branch diverged from remote, reset to match
git fetch origin
git reset --hard origin/main

# Alternative: reset and clean untracked files
git reset --hard origin/main
git clean -fd  # Remove untracked files and directories

Cleaning Untracked Files

Complement git reset with git clean to remove untracked files:

Safe Cleaning Process

# 1. See what would be deleted (dry run)
git clean -n

# 2. See what would be deleted including directories
git clean -nd

# 3. Remove untracked files (force required)
git clean -f

# 4. Remove untracked files and directories
git clean -fd

# 5. Remove ignored files too (careful!)
git clean -fX

# 6. Interactive cleaning
git clean -i

Common Clean Combinations

# Complete reset: undo commits and remove all untracked files
git reset --hard HEAD~1
git clean -fd

# Reset to match remote exactly
git fetch origin
git reset --hard origin/main
git clean -fd

Recovery and Safety

Before Resetting (Safety Measures)

# 1. Check current state
git status
git log --oneline -10

# 2. Create backup branch
git branch backup-before-reset

# 3. Stash uncommitted changes (alternative to backup)
git stash push -m "Before reset backup"

# 4. Note current commit hash
git rev-parse HEAD

Recovery After Reset

Using reflog (Git's safety net):

# View recent HEAD movements
git reflog

# Find the commit you want to return to
# Output shows: abc1234 HEAD@{2}: commit: Important work

# Reset back to that commit
git reset --hard abc1234
# or
git reset --hard HEAD@{2}

Using backup branch:

# If you created a backup branch
git reset --hard backup-before-reset

# Clean up backup after recovery
git branch -d backup-before-reset

Reset vs. Other Commands

Reset vs. Revert

ResetRevert
Moves history backwardsCreates new commit that undoes changes
Dangerous on shared branchesSafe for shared branches
Rewrites historyPreserves history
Use for local changesUse for published commits

Reset vs. Checkout/Switch

ResetCheckout/Switch
Moves branch pointerMoves HEAD pointer
Changes current branchCan switch branches
Can modify staging/working dirOnly changes working directory

Reset vs. Restore

# Old way: Reset to unstage
git reset HEAD file.txt

# New way: Restore from staging
git restore --staged file.txt

# Old way: Reset file to last commit
git checkout HEAD -- file.txt

# New way: Restore file from HEAD
git restore file.txt

Advanced Reset Scenarios

Reset Specific Paths

# Reset specific file to specific commit
git reset abc1234 -- file.txt

# Reset directory to HEAD
git reset HEAD -- src/

# This only affects staging area, not working directory

Interactive Reset

# Reset commits but interactively choose which changes to keep
git reset --mixed HEAD~3
git add -p  # Selectively stage changes
git commit -m "Cleaned up implementation"

Reset in Merge Conflicts

# Abort merge and reset to pre-merge state
git merge --abort

# Or manually reset
git reset --hard HEAD

Best Practices

Do's ✅

  • Always check git status and git log before reset
  • Create backup branches before destructive operations
  • Use --mixed for most unstaging operations
  • Use --soft when you want to recommit differently
  • Use reflog to recover from mistakes

Don'ts ❌

  • Never reset --hard on shared/public branches
  • Don't reset without understanding what you'll lose
  • Avoid reset on commits others have based work on
  • Don't use hard reset without checking git status first

When NOT to Use Reset

# DON'T do this on shared branches
git reset --hard HEAD~1  # Others may have this commit

# DO this instead
git revert HEAD  # Creates new commit undoing changes

Troubleshooting

"I accidentally did a hard reset!"

# Check reflog for recent commits
git reflog

# Reset to before the accident
git reset --hard HEAD@{1}  # Adjust number as needed

"Reset didn't work as expected"

# Check what actually happened
git status
git log --oneline -10
git reflog -10

# Your changes might be in:
# 1. Working directory (if you used --soft or --mixed)
# 2. Stash (if you stashed before reset)
# 3. Another branch (if you created backup)

"Files are still modified after reset"

# Mixed reset leaves working directory unchanged
# Use hard reset to discard all changes
git reset --hard HEAD

# Or restore specific files
git restore file.txt

Examples Summary

# Common reset operations

# Unstage files
git reset HEAD file.txt

# Undo last commit, keep changes staged
git reset --soft HEAD~1

# Undo last commit, unstage changes
git reset --mixed HEAD~1  # or just: git reset HEAD~1

# Completely remove last commit
git reset --hard HEAD~1

# Reset to match remote
git fetch origin && git reset --hard origin/main

# Clean reset (remove commits and untracked files)
git reset --hard HEAD~1 && git clean -fd

Next Steps

Now that you understand Git reset:

  1. Learn Git Revert - Safe way to undo changes on shared branches
  2. Master Git Stash - Temporarily save work without committing
  3. Understand Git Rebase - Another way to modify commit history

Quick Reference

CommandHEADStagingWorkingUse Case
--softRecommit differently
--mixedUnstage changes
--hardDiscard everything