Complete Git Reset Command Reference
Master the art of undoing changes in Git
Git reset is a powerful command for undoing changes. This comprehensive guide covers all essential git reset commands with practical examples and safety information.
(--hard resets here)
(--mixed/default resets here)
(--soft resets here only)
Basic Reset Commands
Moves HEAD pointer but keeps changes staged. Perfect for editing last commit message or combining commits.
$ git commit -m "Initial commit"
$ git add forgotten_file.txt
$ git reset --soft HEAD~1
# Keeps both changes staged
$ git commit -m "Complete initial commit"
[main abc1234] Complete initial commit
Moves HEAD pointer, unstages changes (default --mixed). Use to unstage files while keeping changes.
$ git add .
Changes to be committed: file1.txt, file2.txt
$ git reset HEAD
# Unstage all files
Unstaged changes after reset: file1.txt, file2.txt
$ git reset file.txt
# Unstage specific file
Unstaged changes after reset: file.txt
Moves HEAD pointer, discards all changes. Completely removes the last commit. Use with extreme caution!
$ git commit -m "Buggy commit"
[main def5678] Buggy commit
$ git reset --hard HEAD~1
# Completely removes the commit
HEAD is now at abc1234 Previous good commit
Discard unstaged changes in a specific file. File-level undo that doesn't affect other files.
$ git status
modified: file.txt
$ git checkout -- file.txt
$ git status
nothing to commit, working tree clean
Advanced Reset Techniques
Revert one file to its state at a specific commit. Useful for selectively undoing changes to a single file.
$ git log --oneline -- file.txt
def5678 Update file.txt
abc1234 Initial version
$ git reset abc1234 -- file.txt
# Revert file.txt to abc1234 state
Selectively undo specific lines from last commit. Interactive patch mode for precise control.
$ git reset -p HEAD~1 -- file.txt
diff --git a/file.txt b/file.txt
index 1234567..89abcde 100644
--- a/file.txt
+++ b/file.txt
@@ -1,5 +1,5 @@
-Hello World
+Hello Git
Discard this hunk? [y,n,q,a,d,/,j,J,g,e,?]? y
Unstaged changes after reset: M file.txt
Reset local branch to match remote exactly. Destructive operation that discards all local changes.
$ git fetch origin
remote: Counting objects: 5, done.
remote: Total 5 (delta 3), reused 5 (delta 3)
$ git reset --hard origin/main
HEAD is now at def5678 Latest commit from remote
# WARNING: All local changes will be lost!
Reset all txt files using pathspec. Useful for unstaging groups of files by pattern.
$ git add '*.txt'
$ git status
Changes to be committed: file1.txt, file2.txt
$ git reset '*.txt'
$ git status
Changes not staged for commit: file1.txt, file2.txt
Abort a merge but keep changes. Useful when you want to stop a merge and try a different approach.
$ git merge feature-branch
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
$ git reset --merge
Merge aborted, changes preserved
$ git status
On branch main, nothing to commit
$ git reset --keep HEAD~1
HEAD is now at abc1234 Previous commit
$ git status
Changes not staged for commit: file1.txt, file2.txt
# Local changes are preserved
Dangerous But Powerful Resets
Nuclear reset - makes working directory match last commit exactly. Removes all changes and untracked files.
$ git reset --hard
HEAD is now at abc1234
$ git clean -fd
Removing untracked_file.txt
Removing untracked_dir/
# WARNING: This cannot be undone!
Remove commits from shared history. Requires force push and should only be used on private branches.
$ git reset --hard HEAD~5
HEAD is now at def5678
$ git push --force
+ abc1234...def5678 main -> main (forced update)
# WARNING: This rewrites public history!
Time machine reset to a specific moment. Powerful but dangerous - can cause data loss.
git reset --hard "@{9am yesterday}..@{5pm yesterday}" # Undo all yesterday's work
$ git reset --hard "@{2024-03-15 14:30:00 -0400}"
HEAD is now at abc1234 Commit from that time
# Use git reflog to recover if needed
Pro Reset Patterns
Keep working changes while resetting commits. Preserves uncommitted changes during history manipulation.
$ git stash
Saved working directory and index state
$ git reset --hard HEAD~3
HEAD is now at abc1234
$ git stash pop
Restored working changes
Split a commit into multiple logical changes. Powerful technique for creating clean commit history.
$ git reset --soft HEAD~3
# Rewind 3 commits, keep changes staged
$ git reset -p
# Interactive partial unstage
Discard this hunk? [y,n,q,a,d,/,j,J,g,e,?]? y
$ git commit -m "Feature part 1"
$ git commit -m "Feature part 2"
$ git commit -m "Feature part 3"
Precise branch resynchronization while preserving staged changes. Advanced technique for complex workflows.
$ git fetch origin
$ git reset --hard origin/main --keep-index
# Reset branch but preserve staged changes
$ git stash
# Stash working changes
$ git stash apply
# Reapply working changes
CI/CD safe reset pattern. Uses --force-with-lease which is safer than --force for automated environments.
# In CI/CD pipeline script
git reset --hard $FAILED_COMMIT
HEAD is now at abc1234 Failed commit
git push --force-with-lease
To github.com:user/repo.git
+ def5678...abc1234 main -> main
# Safer than --force as it checks remote state
Standard unstage command. Use to unstage all files while keeping changes in working directory.
$ git add .
Changes to be committed: file1.txt, file2.txt
$ git reset --mixed HEAD
Unstaged changes after reset: file1.txt, file2.txt
$ git status
Changes not staged for commit: file1.txt, file2.txt
Recover from mistaken reset using reflog. Find the commit hash from before the reset and restore to it.
$ git reflog
abc1234 HEAD@{0}: reset: moving to HEAD~1
def5678 HEAD@{1}: commit: Important work
$ git reset --hard def5678
HEAD is now at def5678 Important work
# Recovery successful!
Surgical File History Rewrite
Rewind the entire repository to its state from exactly one day ago. Powerful but dangerous - can cause data loss.
$ git log --oneline -3
abc1234 (HEAD -> main) Today's work
def5678 Yesterday's work
ghi9012 Work from two days ago
$ git reset --hard @{1.day.ago}
HEAD is now at def5678 Yesterday's work
# Repository is now exactly as it was 24 hours ago
$ git status
HEAD detached at def5678
nothing to commit, working tree clean
Retrieve a specific file from 5 commits ago without affecting the rest of your working directory.
$ git log --oneline -7 -- file.txt
abc1234 Current version
def5678 Removed feature X
ghi9012 Added feature Y
jkl3456 Added feature X
# Restore file.txt to its state from 5 commits ago
$ git checkout HEAD@{5} -- file.txt
$ git status
Changes not staged for commit: file.txt
# file.txt now contains its content from 5 commits ago
Replace the current HEAD commit with a new one. Useful for fixing commit messages or adding forgotten changes.
$ git commit -m "Initial implmentation"
[main abc1234] Initial implmentation
# Oops, typo in commit message and forgot a file
$ git add forgotten-file.txt
$ git commit --amend
# Editor opens to fix commit message
[main def5678] Initial implementation
# Commit hash changed, message fixed, file added
Advanced Reflog Navigation
Search through reflog with relative dates to find lost commits by their commit message content.
$ git reflog --relative-date | grep "commit: Add"
abc1234 HEAD@{2 days ago}: commit: Add user
authentication
def5678 HEAD@{3 days ago}: commit: Add database schema
ghi9012 HEAD@{5 days ago}: commit: Add initial project
structure
# Found the commit where authentication was added
$ git show abc1234
commit abc1234...
Author: John Doe
Date: 2 days ago
Add user authentication
Complex command to reset to the first checkout operation found in reflog. Advanced recovery technique.
$ git reflog
abc1234 HEAD@{0}: reset: moving to HEAD~1
def5678 HEAD@{1}: checkout: moving from feature to main
ghi9012 HEAD@{2}: commit: Important work on feature
# Extract the first checkout reference
$ git reset --hard HEAD@{git reflog | grep -m1 "checkout:" |
cut -d' ' -f1}
HEAD is now at def5678
# Now at the state right after the checkout operation
Multi-Level Undo System
Undo the last 3 commits but keep all changes staged. First step in a multi-level undo operation.
$ git log --oneline -4
abc1234 (HEAD -> main) Commit 3
def5678 Commit 2
ghi9012 Commit 1
jkl3456 Base commit
$ git reset --soft HEAD~3
HEAD is now at jkl3456 Base commit
$ git status
Changes to be committed: (all changes from last 3
commits)
Undo 2 more commits, unstaging the changes. Second step in a multi-level undo operation.
# Continuing from previous reset --soft
$ git reset HEAD~2
Unstaged changes after reset: (changes from last 2
commits)
$ git status
Changes not staged for commit: (changes from last 2
commits)
Changes to be committed: (changes from first commit only)
Final step: completely discard all changes. Use with caution as this cannot be undone.
# Continuing from previous reset
$ git reset --hard HEAD~1
HEAD is now at mno7890 (earlier than base commit)
$ git status
nothing to commit, working tree clean
# All changes from the last 3 commits are now gone
Index-Only Reset (Skip Worktree)
Standard unstage command. Resets the index to match HEAD while keeping working directory changes.
$ git add .
Changes to be committed: file1.txt, file2.txt
$ git reset --mixed HEAD
Unstaged changes after reset: file1.txt, file2.txt
$ git status
Changes not staged for commit: file1.txt, file2.txt
# Files are unstaged but changes are preserved
Reset all skip-worktree flags. Useful when you want to start tracking previously ignored files again.
$ git ls-files -v | grep '^S'
S config/local.properties
S temp/test-data.json
# These files have skip-worktree flag set
$ git ls-files -z | xargs -0 git update-index
--no-assume-unchanged
$ git ls-files -v | grep '^S'
# No output - all skip-worktree flags are cleared
$ git status
Changes not staged for commit: config/local.properties,
temp/test-data.json
Advanced Merge Conflict Reset
Abort a merge and reset to ORIG_HEAD (state before merge began). Preserves your working directory changes.
$ git merge feature-branch
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the
result.
# Changed your mind about the merge
$ git reset --merge ORIG_HEAD
Unstaged changes after reset: file.txt
$ git status
Changes not staged for commit: file.txt
no changes added to commit
# Merge aborted, back to pre-merge state
Alternative to --merge with better change preservation. Resets index to specified commit but keeps working tree changes.
$ git reset --keep HEAD~1
Unstaged changes after reset: file1.txt, file2.txt
$ git status
Changes not staged for commit: file1.txt, file2.txt
no changes added to commit
# Working tree changes preserved, index reset to HEAD~1
Always check git status and git log before
using reset commands, especially --hard. Consider using
git revert for public commits instead of resetting, as it
doesn't rewrite history.
Use git reflog to recover from mistaken resets - it keeps
a history of all reference changes for 90 days by default.
When using advanced reset techniques, always:
-
Check
git statusandgit logbefore performing resets - Understand the difference between --soft, --mixed, and --hard resets
- Use
git reflogto recover from mistaken resets - Consider creating a backup branch before performing complex history operations