Skip to content

stash Git Command Guide

The git stash command temporarily shelves (or stashes) changes you’ve made to your working copy so you can work on something else, and then come back and re-apply them later. Stashing is useful when you need to switch contexts quickly without committing incomplete work.

Terminal window
git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
[--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>...]]
git stash show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]
git stash drop [-q|--quiet] [<stash>]
git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
[--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>...]]
git stash clear
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
OptionDescription
-p, --patchInteractively select hunks to stash
-k, --keep-indexKeep staged changes in index
--no-keep-indexDon’t keep staged changes
-u, --include-untrackedInclude untracked files
-a, --allInclude untracked and ignored files
-m <message>, --message <message>Add descriptive message
-q, --quietSuppress status messages
OptionDescription
--statShow diff statistics
--name-onlyShow only changed filenames
--name-statusShow filenames with status
-p, --patchShow full diffs
-u, --include-untrackedShow untracked files in stash
--only-untrackedShow only untracked files
OptionDescription
--indexTry to recreate staged state
-q, --quietSuppress status messages
ParameterDescription
<stash>Stash reference (stash@{0}, stash@{1}, etc.)
<branchname>Name for new branch
<message>Descriptive message for stash
<pathspec>Limit operation to specific paths
Stash Structure:
├── Stash Entry: Complete snapshot of working directory state
├── Index State: What was staged before stashing
├── Working Tree: Unstaged changes
├── Untracked Files: Optionally included files
└── Message: Optional description
Stash References:
├── stash@{0}: Most recent stash
├── stash@{1}: Second most recent
├── stash@{n}: Nth stash from top
└── stash@{/pattern}: Search by message pattern
Comparison Matrix:
├── Stash: Temporary storage, preserves working state
├── Commit: Permanent history, requires clean message
├── Branch: Parallel development, full isolation
├── Reset: Discards changes, cannot recover easily
└── Shelve: Similar to stash (other VCS systems)
Terminal window
# Stash all changes (staged + unstaged)
git stash
# Stash with descriptive message
git stash push -m "WIP: user authentication feature"
# Stash only unstaged changes, keep staged
git stash push --keep-index
# Stash interactively (select hunks)
git stash push --patch
# Include untracked files
git stash push --include-untracked
# Include untracked and ignored files
git stash push --all
Terminal window
# List all stashes
git stash list
# Show stash contents (diff)
git stash show
# Show specific stash
git stash show stash@{1}
# Show stash with full diff
git stash show -p stash@{2}
# Show stash statistics
git stash show --stat
Terminal window
# Apply most recent stash
git stash pop
# Apply specific stash
git stash apply stash@{1}
# Apply and preserve stash
git stash apply stash@{0}
# Apply with index reconstruction
git stash pop --index
Terminal window
# Delete most recent stash
git stash drop
# Delete specific stash
git stash drop stash@{2}
# Delete all stashes
git stash clear
# Create branch from stash
git stash branch feature-fix stash@{1}
Terminal window
# Stash specific files
git stash push -- src/main.c src/utils.h
# Stash by path pattern
git stash push -- '*.log' 'build/'
# Interactive hunk selection
git stash push --patch
# Then use 'y' to stash, 'n' to skip, 's' to split hunks
Terminal window
# Include newly created files
git stash push --include-untracked
# Include everything (tracked, untracked, ignored)
git stash push --all
# Show untracked files in stash
git stash show --include-untracked
# Show only untracked files
git stash show --only-untracked
Terminal window
# Descriptive messages
git stash push -m "Bug fix: login validation"
git stash push -m "Feature: user profile page"
git stash push -m "Refactor: database connection pooling"
# Search stashes by message
git stash list | grep "login"
git stash show stash@{/login}
Terminal window
# Keep staged changes when stashing
git stash push --keep-index
# Apply stash without touching index
git stash apply --index
# Check what's staged vs unstaged
git diff --cached # Staged changes
git diff # Unstaged changes
Terminal window
# Configure stash behavior
git config stash.showStat true # Show stats by default
git config stash.showPatch true # Show patch by default
git config stash.showUntrackedFiles true # Show untracked files
# Configure stash messages
git config stash.useBuiltin true # Use modern stash implementation
# Configure colors
git config color.stash.branch yellow
git config color.stash.added green
git config color.stash.changed red
Terminal window
# Use descriptive messages
git stash push -m "WIP: implement user auth"
# Don't stash instead of committing
# Use stash for temporary context switches
# Clean up regularly
git stash list
git stash drop <old-stashes>
# Use stash branches for complex work
git stash branch feature-fix stash@{0}
Terminal window
# Check before applying
git stash show stash@{0} --stat
# Backup important stashes
git stash show stash@{0} -p > important-changes.patch
# Verify clean application
git status # Should show clean working tree
#!/bin/bash
# Quick context switching with stash
switch_context() {
local task_description="$1"
# Stash current work
if ! git diff --quiet || ! git diff --cached --quiet; then
git stash push -m "Context switch: $task_description"
echo "Work stashed for: $task_description"
fi
# Switch to other task
# ... work on other task ...
# Later: restore work
# git stash pop
}
# Usage
switch_context "urgent bug fix"
Terminal window
# Handle emergency fixes
emergency_fix() {
local fix_branch="hotfix/emergency"
# Stash current work
git stash push -m "Emergency fix - stashed work"
# Create fix branch from main
git checkout main
git pull origin main
git checkout -b "$fix_branch"
# Make emergency fix
# ... edit files ...
git add .
git commit -m "Emergency fix: [description]"
# Deploy and merge
git checkout main
git merge "$fix_branch"
git push origin main
# Restore original work
git checkout original-branch
git stash pop
echo "Emergency fix completed, work restored"
}
Terminal window
# Prepare changes for review
prepare_review() {
local review_branch="review/$(date +%Y%m%d-%H%M%S)"
# Stash current changes
git stash push -m "Code review preparation"
# Create review branch
git checkout -b "$review_branch"
# Apply stashed changes
git stash pop
# Clean up and prepare
git add .
git commit -m "Changes ready for review"
# Push for review
git push -u origin "$review_branch"
echo "Changes prepared for review on branch: $review_branch"
}
Terminal window
# Handle conflicts during apply/pop
git stash pop # May cause conflicts
# Resolve conflicts manually
# Edit conflicted files
# Stage resolved files
git add resolved-file.txt
# Complete the stash application
git commit # Creates merge commit
# Or abort and try different approach
git reset --merge # Abort conflicted merge
git stash apply # Try apply instead of pop
Terminal window
# Find dropped stashes
git fsck --unreachable | grep commit
# Recover specific commit
git show <commit-hash>
git cherry-pick <commit-hash> # If you want to apply it
# Use reflog to find stash operations
git reflog | grep stash
Terminal window
# Handle binary files in stash
git stash push --all # Include everything
# Check binary files in stash
git stash show --name-only | file -
# Apply carefully (binaries may conflict)
git stash show -p | head -50 # Preview before applying
Terminal window
# Speed up stash operations in large repos
git stash push --quiet # Reduce output
# Limit stash scope
git stash push -- <specific-path>
# Use shallow stashes for quick saves
git stash push -m "quick save"
Terminal window
# Handle encoding problems
git config core.quotepath false
# Fix line ending issues
git config core.autocrlf input
# Handle special characters in stash messages
git stash push -m "Fix: encoding issue with ümlauts"
Terminal window
# Handle stashes in submodule repositories
git submodule foreach 'git stash push -m "parent project changes"'
# Apply stashes in submodules
git submodule foreach git stash pop
# Check submodule stash status
git submodule foreach git stash list
#!/bin/bash
# Integrated stash workflow
dev_workflow_stash() {
echo "=== Development Workflow with Stash ==="
# Check current status
if git diff --quiet && git diff --cached --quiet; then
echo "✓ Working tree is clean"
return 0
fi
# Categorize changes
staged=$(git diff --cached --name-only | wc -l)
unstaged=$(git diff --name-only | wc -l)
untracked=$(git status --porcelain | grep "^??" | wc -l)
echo "Changes detected:"
echo " Staged files: $staged"
echo " Unstaged files: $unstaged"
echo " Untracked files: $untracked"
# Intelligent stashing
if [ "$staged" -gt 0 ] && [ "$unstaged" -eq 0 ]; then
echo "Only staged changes - committing instead"
git commit -m "WIP: staged changes"
elif [ "$unstaged" -gt 0 ] && [ "$untracked" -eq 0 ]; then
git stash push -m "WIP: unstaged changes"
echo "✓ Unstaged changes stashed"
elif [ "$untracked" -gt 0 ]; then
git stash push --include-untracked -m "WIP: with untracked files"
echo "✓ Changes stashed including untracked files"
else
git stash push -m "WIP: mixed changes"
echo "✓ Mixed changes stashed"
fi
echo "Ready for context switch"
}
dev_workflow_stash
Terminal window
# Feature development with stash checkpoints
feature_development() {
local feature_name="$1"
echo "Starting feature development: $feature_name"
# Create feature branch
git checkout -b "feature/$feature_name"
# Development loop with stash checkpoints
while true; do
echo "Working on $feature_name..."
# ... development work ...
read -p "Create checkpoint? (y/n/q): " choice
case "$choice" in
y|Y)
git stash push -m "Checkpoint: $(date) - $feature_name"
echo "✓ Checkpoint created"
;;
q|Q)
break
;;
*)
continue
;;
esac
done
# Review checkpoints
echo "Feature checkpoints:"
git stash list | grep "$feature_name"
# Apply final state
git stash pop # Apply most recent
echo "Feature development complete"
}
feature_development "user-dashboard"
Terminal window
# Test changes without committing
test_with_stash() {
echo "Testing changes with stash isolation"
# Stash current work
git stash push -m "Testing: $(date)"
# Run tests on clean state
if ./run-tests.sh; then
echo "✓ Tests passed on clean state"
else
echo "✗ Tests failed on clean state"
return 1
fi
# Apply changes and test again
git stash pop
if ./run-tests.sh; then
echo "✓ Tests passed with changes"
else
echo "⚠ Tests failed with changes - review needed"
return 1
fi
echo "Testing complete"
}
test_with_stash
Terminal window
# Team stash coordination
team_stash_workflow() {
echo "=== Team Stash Workflow ==="
# Check team stash status
echo "Team stash overview:"
git stash list --format="%gd: %gs (%cr)" | head -10
# Identify stashes by team member
echo "Stashes by team member:"
git stash list | while read -r line; do
hash=$(echo "$line" | cut -d: -f1)
author=$(git show --format='%an' --no-patch "$hash")
message=$(git show --format='%s' --no-patch "$hash")
echo "$author: $message"
done | sort | uniq -c | sort -nr
# Find old stashes to clean up
echo "Potentially stale stashes (>30 days):"
git stash list --format="%gd: %gs (%cr)" | while read -r line; do
age=$(echo "$line" | grep -o "[0-9]\+ days ago\|[0-9]\+ weeks ago\|[0-9]\+ months ago" || echo "")
if [[ "$age" == *"month"* ]] || [[ "$age" == *"week"* && "$age" > "4 weeks ago" ]]; then
echo "$line"
fi
done
echo "Team stash review complete"
}
team_stash_workflow
Terminal window
# Analyze stash usage patterns
stash_analytics() {
echo "=== Stash Usage Analytics ==="
# Stash statistics
total_stashes=$(git stash list | wc -l)
echo "Total stashes: $total_stashes"
# Stash frequency
echo "Stash creation timeline:"
git stash list --format='%ai' | cut -d' ' -f1 | sort | uniq -c
# Most common stash messages
echo "Common stash topics:"
git stash list --format='%s' | sed 's/WIP:\|TODO:\|FIX://' | sort | uniq -c | sort -nr | head -10
# Stash size analysis
echo "Stash sizes (lines changed):"
git stash list --format='%gd' | while read -r stash; do
lines=$(git stash show --stat "$stash" | tail -1 | awk '{print $4+$6}')
echo "$stash: $lines lines"
done | sort -k2 -nr | head -10
# Author analysis
echo "Stash authors:"
git stash list --format='%H %an' | while read -r hash author; do
echo "$author"
done | sort | uniq -c | sort -nr
echo "Analytics complete"
}
stash_analytics

What’s the difference between git stash pop and git stash apply?

Section titled “What’s the difference between git stash pop and git stash apply?”

git stash pop applies the stash and removes it from the stash list; git stash apply applies the stash but keeps it in the list for potential re-application.

Use git stash push —include-untracked to stash untracked files, or —all to include untracked and ignored files.

Yes, use git stash push — to stash only specific files or paths.

How do I see what’s in a stash without applying it?

Section titled “How do I see what’s in a stash without applying it?”

Use git stash show to see a summary, or git stash show -p for the full diff.

What happens if I stash with staged changes?

Section titled “What happens if I stash with staged changes?”

By default, staged changes become unstaged when you apply the stash. Use —index when applying to restore the staged state.

Yes, use git stash branch to create a new branch from the stash and apply it there.

Use git fsck —unreachable | grep commit to find dropped stashes, then git show to verify and git cherry-pick to recover.

What’s the difference between stash save and stash push?

Section titled “What’s the difference between stash save and stash push?”

stash push is the modern command (since Git 2.13); stash save is the older deprecated syntax.

Can I stash in the middle of a merge conflict?

Section titled “Can I stash in the middle of a merge conflict?”

No, you must resolve the merge first. Stash only works on a clean working tree state.

Use git stash show —stat to see how many files and lines changed in a stash.

Can stashes be shared between repositories?

Section titled “Can stashes be shared between repositories?”

No, stashes are local to each repository and don’t transfer with push/pull operations.

Use git stash list and pipe to grep, or use stash@{/pattern} syntax for direct reference.

stash@{0} is the most recent, stash@{1} is the second most recent, and so on.

No, stashes are immutable. To modify, apply the stash, make changes, then create a new stash.

How do I handle stashes with binary files?

Section titled “How do I handle stashes with binary files?”

Stashes work with binary files, but conflicts may be harder to resolve. Use —stat to check stash contents before applying.

What’s the performance impact of stashing in large repos?

Section titled “What’s the performance impact of stashing in large repos?”

Stashing is generally fast, but showing large stashes with -p can be slow. Use —stat for quick overview.

Yes, but stashes in submodules are separate. Use git submodule foreach to manage stashes across all submodules.

Create a cron job or hook that runs git stash list and drops stashes older than a certain age.

What’s the difference between stash and shelve?

Section titled “What’s the difference between stash and shelve?”

Stash is Git’s built-in feature; shelve is similar functionality in other version control systems like Perforce.

  1. Context Switching: Temporarily save work to switch to urgent tasks
  2. Code Review Preparation: Clean working tree for reviewing others’ changes
  3. Experimental Development: Try ideas without committing incomplete work
  4. Emergency Fixes: Quick switches to hotfix branches
  5. Branch Management: Clean switches between feature branches
  6. Testing Isolation: Test changes without affecting main development
  7. Collaborative Development: Share work-in-progress without premature commits
  8. Workflow Flexibility: Enable fluid development processes