https://git-scm.com/book/en/v2
Git stash is a powerful command that temporarily shelves (or stashes) changes you've made to your working directory so you can work on something else, and then come back and re-apply them later. Stashing takes your uncommitted changes (both staged and unstaged), saves them away for later use, and then reverts your working directory to match the HEAD commit.
When you stash, Git:
Critical caveat: By default, stash does NOT include untracked files or ignored files. You must use specific flags to include them.
Need to switch branches but aren't ready to commit your current work? Stash it and retrieve it later.
When urgent bug fixes or meetings interrupt your work, stash lets you save your progress without creating messy "WIP" commits.
Try different approaches by stashing your current attempt, testing alternatives, and retrieving or discarding as needed.
Some Git operations require a clean working directory. Stash provides a quick way to achieve this.
Accidentally started work on the wrong branch? Stash your changes, switch branches, and apply them where they belong.
Temporarily remove uncommitted changes to test if a bug exists in the committed code or only in your modifications.
Imagine you're working on a feature when you need to switch to a hotfix:
Before Stash:
Working Directory: Modified files (not committed)
file1.js - modified
file2.css - modified and staged
After git stash:
Working Directory: Clean (matches HEAD)
Stash Stack: [Stash@{0}: WIP on feature: abc1234 Last commit message]
After git stash pop:
Working Directory: Changes restored
file1.js - modified (restored)
file2.css - modified and staged (restored)
Stash Stack: [Empty - stash removed after applying]
Save your current work:
# Stash all tracked changes
git stash
# Or with a descriptive message
git stash push -m "Work in progress on login feature"
What happens:
Restore your work:
# Apply most recent stash and remove it from stack
git stash pop
# Apply most recent stash but keep it in stack
git stash apply
Include untracked files in your stash:
# Stash tracked and untracked files
git stash -u
# or
git stash --include-untracked
# Stash everything including ignored files
git stash -a
# or
git stash --all
View all stashes:
git stash list
Output example:
stash@{0}: WIP on feature: abc1234 Add login form
stash@{1}: On main: def5678 Fix navigation bug
stash@{2}: WIP on feature: ghi9012 Update styles
Apply a specific stash:
# Apply stash@{1}
git stash apply stash@{1}
# Pop stash@{2}
git stash pop stash@{2}
Selectively stash specific changes:
# Interactively choose what to stash
git stash -p
# or
git stash --patch
Git will show each change and prompt:
Stash this hunk [y,n,q,a,d,e,?]?
Options:
y - Stash this hunkn - Don't stash this hunkq - Quit (don't stash this or remaining hunks)a - Stash this and all remaining hunksd - Don't stash this or remaining hunkse - Manually edit the hunk? - Show helpStash only certain files:
# Stash specific files
git stash push -m "Stashing config files" config.js settings.json
# Stash files matching a pattern
git stash push -m "Stashing all CSS" src/**/*.css
# Show summary of most recent stash
git stash show
# Show summary of specific stash
git stash show stash@{1}
Output example:
file1.js | 10 +++++-----
file2.css | 3 +++
2 files changed, 8 insertions(+), 5 deletions(-)
# Show full diff of most recent stash
git stash show -p
# Show full diff of specific stash
git stash show -p stash@{2}
# Basic stash
git stash
# Stash with message
git stash push -m "Description of changes"
# Stash including untracked
git stash -u
# Stash including ignored files
git stash -a
# Stash specific files
git stash push file1.js file2.css
# Stash only staged changes
git stash --staged
# Apply most recent stash (keeps in stack)
git stash apply
# Apply specific stash
git stash apply stash@{1}
# Pop most recent stash (removes from stack)
git stash pop
# Pop specific stash
git stash pop stash@{1}
# List all stashes
git stash list
# Show stash summary
git stash show
# Show stash diff
git stash show -p
# Remove most recent stash
git stash drop
# Remove specific stash
git stash drop stash@{1}
# Remove all stashes
git stash clear
# Create new branch and apply stash
git stash branch new-feature-branch
# Create branch from specific stash
git stash branch bugfix-branch stash@{1}
This is especially useful when:
If conflicts occur when applying a stash:
# Attempt to apply stash
git stash apply
# Output: CONFLICT (content): Merge conflict in file.js
# Fix conflicts manually
# Edit conflicting files
# Stage resolved files
git add file.js
# Stash remains in stack - manually drop if needed
git stash drop
Alternative approach:
# Create branch from conflicting stash
git stash branch temp-branch stash@{0}
# Resolve conflicts in the new branch
# When done, merge back to original branch
# Stash only what's in staging area
git stash --staged
# Or keep staged changes, stash unstaged
git stash --keep-index
Use case: You've staged some changes for commit but want to stash other modifications temporarily.
git stash push -m "Login form validation - needs testing"
Better than default "WIP on branch" messages when managing multiple stashes.
# Useful for cleaning up changes before pulling
git stash
git pull
git stash pop
# Export stash to patch file
git stash show -p stash@{0} > my-changes.patch
# Later, apply the patch
git apply my-changes.patch
| Aspect | Stash | Commit |
|---|---|---|
| Permanence | Temporary storage | Permanent history |
| Visibility | Not part of branch history | Part of branch history |
| Use Case | Work in progress | Completed work |
| Sharing | Local only | Can be pushed/shared |
| Organization | Stack-based | Tree-based |
✅ Incomplete work you'll return to soon
✅ Quick context switching
✅ Experimenting with different approaches
✅ Cleaning working directory temporarily
✅ Completed logical units of work
✅ Changes you want to share
✅ Milestones you want to preserve
✅ Work you want in project history
# You're working on feature-a
git stash
git checkout main
# Do something on main
git checkout feature-a
git stash pop
# You have uncommitted changes
git stash
git pull origin main
git stash pop
# Resolve any conflicts
# Stash to test if bug exists in clean state
git stash
# Run tests
# If bug persists, it's not your changes
git stash pop
# Oops, started work on wrong branch
git stash
git checkout correct-branch
git stash pop
# Uncommitted changes block rebase
git stash
git rebase main
git stash pop
# Safety backup before risky operation
git stash
# Try risky git operation
# If it fails:
git stash pop # Restore your work
Stashes are stored as special commits in .git/refs/stash. Each stash is actually:
Stash structure:
working directory changes
/
stash commit --- index changes
\
base commit (HEAD when stashed)
Stashes use Git's reflog mechanism:
# View stash reflog
git reflog show stash
If you accidentally dropped a stash:
# Find lost stash in reflog
git fsck --unreachable | grep commit
# Or use reflog
git reflog stash
# Recover using commit hash
git stash apply <commit-hash>
Always check what's in a stash before applying:
git stash show -p stash@{0}
This prevents unexpected conflicts or overwrites.
git stash push -m "Auth refactor - needs security review"
git stash list # Review what you have
git stash clear # Remove all when done
git stash pop for one-time stashesgit stash apply when reusing stashesgit stash -u
git stash branch new-feature
Problem: Accumulating dozens of old stashes
Solution: Regularly run git stash list and clean up
Problem: New files aren't included by default
Solution: Use git stash -u when you have new files
Problem: Multiple stashes, applying the wrong one
Solution: Use git stash show -p stash@{n} to verify first
Problem: Stash conflicts with current work
Solution: Use git stash branch to isolate conflicts
Problem: Using git stash drop or git stash clear carelessly
Solution: Review with git stash show before dropping
# Create stash
git stash # Stash tracked files
git stash -u # Include untracked
git stash -a # Include ignored files
git stash push -m "message" # With description
git stash -p # Interactive/partial stash
git stash push file1 file2 # Specific files
git stash --staged # Only staged changes
# Apply stash
git stash pop # Apply + remove
git stash apply # Apply + keep
git stash apply stash@{n} # Apply specific stash
# View stashes
git stash list # List all stashes
git stash show # Summary of latest
git stash show -p # Full diff of latest
git stash show stash@{n} # Specific stash
# Manage stashes
git stash drop # Remove latest
git stash drop stash@{n} # Remove specific
git stash clear # Remove all
git stash branch <branch> # Create branch from stash
# Recovery
git fsck --unreachable | grep commit # Find dropped stash
git stash apply <commit-hash> # Recover dropped stash
Create helpful aliases in your .gitconfig:
[alias]
# Stash shortcuts
st = stash
stl = stash list
stp = stash pop
sta = stash apply
sts = stash show -p
stu = stash -u
# Stash with message
stm = "!f() { git stash push -m \"$1\"; }; f"
# Show all stashes with diffs
stall = "!git stash list | cut -d: -f1 | xargs -I {} sh -c 'echo \"\\n{}:\"; git stash show -p {}'"
# Check for conflicts
git stash show -p
# Try creating a branch instead
git stash branch temp-fix
# Or apply without staging
git stash apply --index
# Error: "Your local changes would be overwritten"
git stash
git checkout other-branch
# Check reflog
git reflog stash
# Or find unreachable commits
git fsck --unreachable | grep commit
git show <commit-hash>
git stash apply <commit-hash>
Git stash is an essential tool for managing work-in-progress changes. It provides a clean, reversible way to temporarily set aside modifications, enabling smooth context switching and experimentation. Unlike commits, stashes are meant to be temporary and local, making them perfect for day-to-day workflow interruptions.
Key takeaways:
-u when needed