Git Stash and Stash Management: Save Work Without Committing
Master git stash for saving uncommitted changes, named stashes, stash list management, and when to use stash vs commit in production workflows.
Git Stash and Stash Management: Save Work Without Committing
git stash is the command you reach for when you’re in the middle of something and need to switch contexts immediately. Maybe production is on fire and you need to pull the latest main. Maybe your code review came back and you need to switch branches. Maybe you just realized you’re on the wrong branch.
Stash saves your uncommitted changes — both staged and unstaged — onto a stack, leaving your working directory clean. You can pop them back later, apply them to a different branch, or drop them entirely. It’s Git’s answer to “I’m not ready to commit but I need a clean slate.”
This post covers the complete stash toolkit: named stashes, selective stashing, stash list management, and the scenarios where stash is the wrong tool.
When to Use / When Not to Use
Use Git Stash When
- Context switching — You need to switch branches but have uncommitted work
- Emergency fixes — Production is broken and you’re in the middle of a feature
- Experimentation — You want to try something without committing to it
- Pull rebase — You need a clean working directory for
git pull --rebase - Code review switches — You need to check out a PR branch while working on something else
Do Not Use Git Stash When
- Long-term storage — Stash is not a backup. Use branches for work you want to keep
- Sharing work — Stash is local-only. Push branches to share with teammates
- Completed features — If the work is done, commit it. Don’t stash finished code
- Large changesets — Stashing hundreds of files is a sign you should commit more frequently
Core Concepts
Git stash operates as a stack of saved changesets:
| Command | Description | Effect |
|---|---|---|
git stash | Save current changes | Working directory becomes clean |
git stash list | Show all stashes | Displays stash stack |
git stash pop | Apply and remove top stash | Restores changes, removes from stack |
git stash apply | Apply without removing | Restores changes, keeps on stack |
git stash drop | Remove a stash | Deletes from stack |
git stash clear | Remove all stashes | Empties the entire stack |
Each stash is a commit-like object that stores both the working directory and the index state.
graph LR
A[Working Directory] -->|git stash| B["stash@{0}"]
B -->|git stash| C["stash@{1}"]
C -->|git stash| D["stash@{2}"]
D -->|git stash pop| E[Working Directory]
Architecture and Flow Diagram
The complete stash lifecycle from creation through application or cleanup:
graph TD
A[Uncommitted Changes] -->|git stash| B[Stash Stack]
B -->|git stash list| C[View Stash List]
C -->|Decision| D{What to do?}
D -->|Restore + Remove| E[git stash pop]
D -->|Restore + Keep| F[git stash apply]
D -->|Delete One| G[git stash drop]
D -->|Delete All| H[git stash clear]
E --> I[Clean Working Directory]
F --> I
G --> B
H --> J[Empty Stack]
Step-by-Step Guide
1. Basic Stash Usage
The simplest form saves everything and cleans your working directory:
# Save all changes (staged and unstaged)
git stash
# Working directory is now clean
git status
# On branch feature/login
# nothing to commit, working tree clean
# Switch branches
git checkout main
# Do your emergency fix...
git commit -m "fix: resolve production issue"
# Return to your feature branch
git checkout feature/login
# Restore your stashed changes
git stash pop
2. Named Stashes
Give your stashes meaningful names so you can find them later:
# Stash with a message
git stash push -m "WIP: user authentication flow - 60% complete"
# Stash with a descriptive name
git stash push -m "feat: add password validation"
# List stashes with messages
git stash list
# stash@{0}: On feature/login: WIP: user authentication flow - 60% complete
# stash@{1}: On feature/login: feat: add password validation
# stash@{2}: On main: WIP: debug production memory leak
3. Selective Stashing
Stash only specific files or use the --keep-index flag:
# Stash only unstaged changes (keep staged changes)
git stash --keep-index
# Stash including untracked files
git stash --include-untracked
# or
git stash -u
# Stash including ignored files
git stash --all
# or
git stash -a
# Stash specific files (Git 2.13+)
git stash push -m "partial stash" -- src/auth.ts src/utils.ts
4. Managing the Stash List
Keep your stash list organized and clean:
# View all stashes
git stash list
# Apply a specific stash (by index)
git stash apply stash@{2}
# Pop a specific stash
git stash pop stash@{1}
# Drop a specific stash
git stash drop stash@{0}
# Show what's in a stash without applying
git stash show stash@{1}
# Or with full diff
git stash show -p stash@{1}
# Clear all stashes
git stash clear
5. Creating Branches from Stashes
Turn a stash into a proper branch:
# Create a branch from the latest stash
git stash branch feature/auth-from-stash
# Create a branch from a specific stash
git stash branch feature/password-validation stash@{2}
# This creates the branch, checks it out, and applies the stash
# The stash is automatically dropped after successful application
Production Failure Scenarios + Mitigations
| Scenario | What Happens | Mitigation |
|---|---|---|
| Stash conflict on pop | The codebase changed since stashing, causing conflicts | Resolve conflicts like a merge conflict; use git stash show -p to review before popping |
| Stash loss | git stash clear or accidental drop removes work | Stash is stored as commits — use git reflog to recover lost stashes |
| Stash stack overflow | Dozens of unnamed stashes become unmanageable | Name every stash; review and clean stash list weekly |
| Stash on wrong branch | Stashed changes don’t apply cleanly to the target branch | Use git stash branch to create a new branch from the stash |
| Untracked files lost | git stash without -u doesn’t save untracked files | Always use git stash -u if you have new files |
| Stash as permanent storage | Work sits in stash for weeks | Stash is local and fragile; use branches for anything you want to keep |
Trade-offs
| Aspect | Advantage | Disadvantage |
|---|---|---|
| Speed | Instant context switch without commit | Changes are not shared with team |
| Flexibility | Can apply to any branch | Conflicts if target branch diverged |
| Organization | Named stashes with messages | Stack can become cluttered over time |
| Safety — Changes are saved as commits | Recoverable via reflog if accidentally dropped | Not visible in normal git log |
| Local-only | No remote pollution | Work is lost if disk fails |
| Selective stashing | Stash only what you need | Complex syntax for partial stashes |
Implementation Snippets
Stash Alias Configuration
# Add to ~/.gitconfig
[alias]
st = status
sl = stash list
sp = stash pop
sa = stash apply
sd = stash drop
ss = stash show
sn = "!f() { git stash push -m \"$*\"; }; f"
sc = stash clear
sb = "!f() { git stash branch \"$1\" \"${2:-stash@{0}}\"; }; f"
Stash Review Script
#!/bin/bash
# scripts/review-stash.sh
# Review all stashes and decide what to keep
echo "=== Stash Review ==="
echo ""
git stash list | while IFS=: read -r ref message; do
echo "--- $ref ---"
echo "Message:$message"
echo "Files changed:"
git stash show --stat "$ref" 2>/dev/null
echo ""
echo "Apply this stash? (y/n/d for drop)"
read -r action
case $action in
y) git stash apply "$ref" ;;
d) git stash drop "$ref" ;;
*) echo "Skipped" ;;
esac
echo ""
done
Pre-switch Hook — Auto-Stash
#!/bin/bash
# scripts/auto-stash-switch.sh
# Automatically stash before switching branches
BRANCH=$1
if [ -z "$BRANCH" ]; then
echo "Usage: auto-stash-switch.sh <branch>"
exit 1
fi
# Check for uncommitted changes
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Uncommitted changes detected. Stashing..."
git stash push -m "Auto-stash before switching to $BRANCH"
git checkout "$BRANCH"
echo "Switched to $BRANCH. Changes stashed."
echo "Run 'git stash pop' when ready to restore."
else
git checkout "$BRANCH"
echo "Switched to $BRANCH (no changes to stash)."
fi
Stash Age Monitor
#!/bin/bash
# scripts/stash-age-check.sh
# Warn about stashes older than 7 days
MAX_AGE_DAYS=7
THRESHOLD=$(date -d "$MAX_AGE_DAYS days ago" +%s 2>/dev/null || date -v-"${MAX_AGE_DAYS}d" +%s)
echo "=== Stash Age Report ==="
echo ""
git stash list --format='%gd %gs' | while read -r ref message; do
# Get the commit date of the stash
STASH_DATE=$(git log -1 --format='%ct' "$ref" 2>/dev/null)
if [ -n "$STASH_DATE" ] && [ "$STASH_DATE" -lt "$THRESHOLD" ]; then
echo "WARNING: $ref is older than $MAX_AGE_DAYS days"
echo " Message: $message"
echo ""
fi
done
Observability Checklist
- Logs: Not typically applicable — stash is a local operation
- Metrics: Track stash frequency per developer (high frequency may indicate commit discipline issues)
- Alerts: Alert when stash count exceeds 10 per developer or stashes older than 7 days exist
- Dashboards: Display stash count, average stash age, and stash-to-branch conversion rate
- Code Review: Check for stashed work during code reviews — stashed code should be committed or discarded
Security and Compliance Notes
- Local-only: Stash data never leaves your machine — it’s stored in
.git/refs/stash - No audit trail: Stash operations are not visible in remote logs or PR history
- Compliance gap: For regulated environments, all code changes should be committed and reviewed — stash bypasses this
- Data sensitivity: Stashed changes may contain sensitive data (API keys, credentials) — never stash secrets
- Recovery: Lost stashes can be recovered via
git reflogwithin the reflog retention period
Common Pitfalls and Anti-Patterns
- The Stash Graveyard — Dozens of unnamed stashes accumulate over months. Name every stash and clean up weekly.
- Stash as Commit Substitute — Using stash instead of committing finished work loses history and prevents code review.
- Pop Without Checking — Popping a stash onto the wrong branch creates conflicts. Always verify your branch before popping.
- Ignoring Untracked Files —
git stashwithout-uleaves new files behind, causing confusion when you return. - Stash Sharing Myth — Stash is local-only. You cannot share stashes with teammates. Use branches for shared work.
- Conflict Resolution Failure — When stash pop conflicts, the stash is NOT removed. You must resolve conflicts and then
git stash drop. - Stashing Secrets — Stashed changes may contain hardcoded credentials. Always check what you’re stashing.
Quick Recap Checklist
- Use
git stashfor temporary context switching, not long-term storage - Name every stash with
git stash push -m "description" - Use
git stash -uto include untracked files - Review stash list regularly and clean up old stashes
- Use
git stash show -pto review contents before applying - Use
git stash branchto convert stashes to proper branches - Never stash secrets or sensitive data
- Resolve conflicts after
git stash popbefore dropping the stash - Keep stash count under 10 per developer
- Commit finished work instead of stashing it
Stash vs Commit vs Worktree
| Aspect | Stash | Commit | Worktree |
|---|---|---|---|
| Persistence | Local, fragile, expires | Permanent in history | Permanent, independent |
| Shareability | Cannot be shared | Pushed to remote | Each worktree is local |
| Recovery | Via reflog if dropped | Always recoverable | N/A — files are on disk |
| Use case | Quick context switch | Completed or checkpointed work | Parallel branch work |
| Disk overhead | Minimal (one object) | Minimal (one object) | Full working directory copy |
| Visibility | Hidden from git log | Visible in git log | Visible via git worktree list |
| Best for | Hours of work, local only | Anything worth keeping | Days of parallel development |
Stash Hygiene Checklist
- Name every stash —
git stash push -m "descriptive message" - Apply promptly — Don’t let stashes sit for more than a few days
- Review before applying —
git stash show -p stash@{n}to confirm contents - Drop after applying — Use
popinstead ofapplyunless you need to keep it - Weekly cleanup — Run
git stash listand drop anything older than a week - Convert old stashes — Use
git stash branch <name>for stashes you still need - Never stash secrets — Check for credentials before stashing
- Include untracked files — Use
-uflag when you have new files - Keep count under 10 — More than 10 stashes means you’re using stash wrong
- Document stash purpose — If you can’t explain why it’s stashed, drop it
Interview Q&A
git stash pop and git stash apply?git stash pop applies the stash and removes it from the stash stack. If there are conflicts, the stash remains on the stack so you can retry after resolving.
git stash apply applies the stash without removing it from the stack. This is useful when you want to apply the same stash to multiple branches or keep it as a backup.
In practice, use pop for the common case and apply when you need to preserve the stash.
Stashes are stored as commits, so they appear in the reflog. To recover a lost stash:
- Run
git reflogto find the stash commit - Look for entries like
stash@{0}orWIP on branch - Note the commit SHA
- Run
git stash apply <sha>to restore it
This works as long as the reflog hasn't been pruned (default retention is 90 days).
Use a branch when the work is complete enough to commit, when you need to share it with teammates, or when you want it to appear in the project history. Branches are visible, shareable, and permanent.
Use a stash when you need a quick context switch, when the work is too incomplete to commit meaningfully, or when you're experimenting and aren't sure if the changes are worth keeping.
Rule of thumb: if you'd be upset losing the work, it belongs on a branch, not in a stash.
Yes, since Git 2.13, you can stash specific files:
git stash push -m "partial stash" -- src/auth.ts src/utils.ts
Alternatively, use --keep-index to stash only unstaged changes while keeping staged changes in the working directory. Or use git stash --patch (or git stash -p) to interactively select which hunks to stash, similar to git add -p.
Resources
- Git stash documentation — Official Git documentation
- Git reflog for recovery — Recovering lost stashes
- Git book: Stashing and Cleaning — Comprehensive guide
- Interactive stash with -p — Patch mode for selective stashing
- Git aliases for productivity — Speed up your workflow
Category
Related Posts
Git Worktree for Parallel Work: Multiple Branches Simultaneously
Master git worktree to work on multiple branches simultaneously without stashing or cloning. Learn parallel development workflows, management commands, and best practices.
Master git add: Selective Staging, Patch Mode, and Staging Strategies
Master git add including selective staging, interactive mode, patch mode, and staging strategies for clean atomic commits in version control.
Git Aliases and Custom Commands: Productivity Through Automation
Create powerful Git aliases, custom scripts, and command extensions. Learn git extras, shell function integration, and team-wide alias standardization for faster workflows.