Skip to content

reset Git Command Guide

The git reset command resets the current branch head (HEAD) to a specified state, optionally modifying the index and working tree. It can move the branch pointer, reset staged changes, or completely reset the repository state.

Terminal window
git reset [-q] [<tree-ish>] [--] <pathspec>...
git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>...]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
ModeDescription
--softReset HEAD only, keep index and working tree
--mixedReset HEAD and index, keep working tree (default)
--hardReset HEAD, index, and working tree
--mergeReset merge state, keep working tree
--keepReset HEAD but keep uncommitted changes
OptionDescription
--patch, -pInteractively select hunks to reset
--pathspec-from-file=<file>Read pathspec from file
--pathspec-file-nulUse NUL delimiter for pathspec file
-q, --quietSuppress output
ParameterDescription
<commit>Target commit to reset to (default: HEAD)
<tree-ish>Tree object to reset index entries from
<pathspec>Files/directories to reset in index
Repository Areas:
├── HEAD: Current branch pointer
├── Index: Staging area (next commit)
└── Working Tree: Actual files
Reset Impact by Mode:
├── --soft: Moves HEAD only
├── --mixed: Moves HEAD + resets index
└── --hard: Moves HEAD + resets index + working tree
Command Comparison:
├── git reset --hard: Destroys uncommitted changes
├── git checkout <commit>: Switches to commit (detached HEAD)
├── git revert: Creates new commit that undoes changes
├── git restore: Modern way to unstage/restore files
└── git reset --soft: Rewinds commits without changing files
Terminal window
# Undo last commit but keep changes staged
git reset --soft HEAD~1
# Undo multiple commits softly
git reset --soft HEAD~3
# Reset to specific commit softly
git reset --soft abc123
Terminal window
# Unstage all changes (default behavior)
git reset
# Unstage specific file
git reset HEAD file.txt
# Reset index to match HEAD
git reset HEAD
# Reset to previous commit (unstages changes)
git reset HEAD~1
Terminal window
# Reset everything to last commit (destroys changes)
git reset --hard
# Reset to previous commit (destroys all changes)
git reset --hard HEAD~1
# Reset to specific commit
git reset --hard abc123
# Force reset to remote branch
git reset --hard origin/main
Terminal window
# Reset specific files in index
git reset HEAD file1.txt file2.txt
# Reset directory in index
git reset HEAD src/
# Use pathspec for complex patterns
git reset HEAD "*.tmp"
Terminal window
# Interactively unstage hunks
git reset --patch
# Interactively reset specific files
git reset --patch HEAD file.txt
# Choose hunks to keep staged
# y: stage this hunk
# n: do not stage this hunk
# q: quit
Terminal window
# Move branch pointer back (keep files)
git reset --soft HEAD~2
# Create new branch from current state
git branch backup-branch
git reset --hard HEAD~5
# Reset to remote branch
git fetch origin
git reset --hard origin/main
Terminal window
# Abort merge and reset to pre-merge state
git reset --merge
# Keep working tree but reset merge state
git reset --merge HEAD
# Reset but keep uncommitted changes
git reset --keep HEAD~1
Terminal window
# Configure reset behavior
git config reset.quiet false # Show reset output
git config advice.statusHints true # Show status hints
# Configure reflog
git config core.logAllRefUpdates true # Enable reflog
git config gc.reflogExpire 90.days # Reflog expiration
Terminal window
# Always create backup before destructive reset
git branch backup-before-reset
# Check what will be lost
git status
git diff HEAD
# Use reflog to recover
git reflog
git reset --hard HEAD@{1} # Recover from backup
# Verify reset result
git log --oneline -5
git status
Terminal window
# Choose reset type based on situation:
# - --soft: Rewind commits, keep changes for recommit
# - --mixed: Unstage changes, keep in working tree
# - --hard: Complete reset, lose all changes
# - --merge: Abort merge, keep working tree
# - --keep: Safe rewind, preserve uncommitted changes
# General rule: Use --soft for safe rewinds, --hard only when sure
#!/bin/bash
# Safe commit rewriting with reset
rewrite_commits() {
local commits_to_rewind="$1"
echo "Rewriting last $commits_to_rewind commits..."
# Create backup
git branch backup-rewrite
# Soft reset to rewind commits
git reset --soft HEAD~"$commits_to_rewind"
# Make changes to combined commit
# Edit files, stage changes
git add .
git commit -m "Combined commit message"
echo "Commits rewritten successfully"
echo "Backup available in: backup-rewrite"
}
rewrite_commits 3
Terminal window
# Clean up feature branch before merge
cleanup_feature_branch() {
local base_branch="${1:-main}"
echo "Cleaning up feature branch for merge..."
# Fetch latest base branch
git fetch origin "$base_branch"
# Reset to match base branch
git reset --hard "origin/$base_branch"
# Or interactively clean up commits
git reset --soft "origin/$base_branch"
git reset --patch HEAD # Selectively unstage
echo "Feature branch cleaned up"
}
cleanup_feature_branch "develop"
Terminal window
# Recover from accidental reset
recover_from_reset() {
echo "Attempting to recover from reset..."
# Check reflog for recovery points
git reflog --oneline -10
# Recover to specific reflog entry
git reset --hard HEAD@{2} # Go back 2 steps
# Or checkout specific commit
git checkout abc123 # Detached HEAD state
# Create new branch from recovered state
git checkout -b recovered-state
echo "Recovery attempt complete"
echo "Check git log and git status"
}
recover_from_reset
Terminal window
# Recover from accidental hard reset
recover_hard_reset() {
echo "Recovering from accidental hard reset..."
# Check reflog immediately
git reflog
# Reset to before the hard reset
git reset --hard HEAD@{1}
# If reflog doesn't help, check other branches
git branch -a
git checkout other-branch
# Last resort: Recover from remote
git fetch origin
git reset --hard origin/main
}
recover_hard_reset
Terminal window
# Handle reset during merge conflicts
handle_reset_conflicts() {
echo "Handling reset during conflicts..."
# Check current state
git status
# Use appropriate reset mode
if [ -n "$(git diff --cached)" ]; then
# Staged changes exist
git reset --merge # Reset merge state
else
# No staged changes
git reset --keep # Safe reset
fi
# Clean up untracked files if needed
git clean -fd
}
handle_reset_conflicts
Terminal window
# Handle reset with uncommitted changes
safe_reset_with_changes() {
echo "Safe reset with uncommitted changes..."
# Stash changes first
git stash push -m "Before reset"
# Perform reset
git reset --hard HEAD~2
# Reapply changes if needed
git stash pop
# Handle conflicts if they occur
# Resolve conflicts manually
# git add resolved-files
# git commit (if needed)
}
safe_reset_with_changes
Terminal window
# Handle reset with remote branches
handle_remote_reset() {
echo "Handling reset with remote branches..."
# Fetch latest remote state
git fetch origin
# Check remote vs local
git log --oneline HEAD..origin/main # Remote ahead
git log --oneline origin/main..HEAD # Local ahead
# Reset to match remote
git reset --hard origin/main
# Or rebase local changes
git rebase origin/main
}
handle_remote_reset
Terminal window
# Fix commit message without changing content
fix_commit_message() {
echo "Fixing commit message..."
# Soft reset to edit last commit
git reset --soft HEAD~1
# Amend with new message
git commit --amend -m "Fixed commit message"
echo "Commit message fixed"
}
fix_commit_message
Terminal window
# Reset feature branch to clean state
reset_feature_branch() {
local base_branch="$1"
echo "Resetting feature branch to $base_branch..."
# Fetch latest base
git fetch origin "$base_branch"
# Hard reset to base (destructive!)
git reset --hard "origin/$base_branch"
# Clean up any extra files
git clean -fd
echo "Feature branch reset to clean state"
echo "WARNING: All local changes lost!"
}
reset_feature_branch "main"
Terminal window
# Clean up messy commit history
interactive_cleanup() {
echo "Interactive commit cleanup..."
# Create backup
git branch backup-before-cleanup
# Interactive reset to clean up commits
git reset --soft HEAD~5 # Rewind 5 commits
# Stage changes selectively
git add -p # Interactive staging
# Create clean commit
git commit -m "Clean consolidated commit"
echo "Commit history cleaned up"
echo "Backup available: backup-before-cleanup"
}
interactive_cleanup
Terminal window
# Complete repository state reset
complete_reset() {
local target_commit="$1"
echo "Complete repository reset to $target_commit..."
# Backup current state
git tag backup-$(date +%Y%m%d-%H%M%S)
# Hard reset to target
git reset --hard "$target_commit"
# Clean untracked files
git clean -fd
# Reset submodules if any
git submodule foreach git reset --hard
echo "Repository completely reset"
echo "Backup tag created for recovery"
}
complete_reset "abc123"
Terminal window
# Manage resets in collaborative environment
collaborative_reset() {
local target_branch="$1"
local reset_type="${2:-soft}"
echo "Collaborative reset to $target_branch..."
# Check if branch is shared
if git branch -r | grep -q "origin/$target_branch"; then
echo "WARNING: Target branch is shared"
echo "This may affect other collaborators"
# Notify team (implement notification)
# send_team_notification "Resetting $target_branch"
# Use force push after reset
force_push=true
fi
# Perform reset
case "$reset_type" in
"soft")
git reset --soft "$target_branch"
;;
"mixed")
git reset --mixed "$target_branch"
;;
"hard")
git reset --hard "$target_branch"
;;
esac
# Push if needed
if [ "$force_push" = true ]; then
git push --force-with-lease origin "$target_branch"
fi
echo "Collaborative reset complete"
}
collaborative_reset "main" "soft"

What’s the difference between reset —soft, —mixed, and —hard?

Section titled “What’s the difference between reset —soft, —mixed, and —hard?”

—soft moves HEAD only (keeps changes staged); —mixed moves HEAD and unstages changes (default); —hard moves HEAD, unstages, and discards working tree changes.

Check git reflog for the commit before reset, then git reset —hard . If reflog is gone, changes are permanently lost.

Yes, git reset HEAD unstages specific files. For working tree, use git checkout HEAD or git restore .

What’s the difference between reset and revert?

Section titled “What’s the difference between reset and revert?”

reset rewinds history (changes existing commits); revert creates new commit that undoes changes (preserves history).

git fetch origin, then git reset —hard origin/branch-name. This discards local changes and matches remote exactly.

Use git reset —merge to abort merge and return to pre-merge state. Use —hard only if you want to lose merge conflict resolutions.

Create backup branch first: git branch backup, then reset. Use —soft for safety, check git status and git log after reset.

git reset —hard for complete reset, or —soft to keep changes staged for recommit.

No, reset only affects current branch. Other branches remain unchanged unless you explicitly reset them too.

What’s the difference between reset and checkout?

Section titled “What’s the difference between reset and checkout?”

reset changes current branch history; checkout switches to different branch/commit (may create detached HEAD).

How do I reset the index but keep working tree?

Section titled “How do I reset the index but keep working tree?”

git reset (default —mixed mode) or git reset —mixed. This unstages all changes but keeps them in working tree.

git reset —hard HEAD~1 after merge undoes it completely. For safer approach, use git revert -m 1 .

What’s the impact of reset on collaborators?

Section titled “What’s the impact of reset on collaborators?”

reset —hard on shared branches requires force push and affects collaborators. They must reset their local branches to match.

git reset HEAD unstages the file, or git checkout HEAD resets working tree (use git restore for modern approach).

Yes, git reset unstages all changes, or git reset HEAD unstages specific file.

What’s the difference between reset and restore?

Section titled “What’s the difference between reset and restore?”

reset modifies branch history and index; restore is modern command for unstaging/discarding files without affecting branch history.

  1. Commit History Management: Rewind commits to fix mistakes or clean up history
  2. Staging Area Control: Unstage files and changes before committing
  3. Branch State Management: Reset branches to match remote or clean states
  4. Merge Conflict Resolution: Abort merges and return to pre-merge state
  5. Repository State Cleanup: Reset to clean state for fresh development
  6. Collaborative Development: Synchronize local branches with remote state