Stashing allows you to save your current work-in-progress changes and switch to a clean working directory. It’s perfect for when you need to quickly switch contexts without committing half-done work.
What is Stashing?
A stash is a temporary storage area for uncommitted changes. It saves both staged and unstaged modifications, then reverts your working directory to match the HEAD commit.
Basic Stashing
Save Your Changes
# Stash current changes
git stash
# Equivalent to:
git stash push
Restore Your Changes
# Apply most recent stash and remove it from stash list
git stash pop
# Apply most recent stash but keep it in stash list
git stash apply
View Stashed Changes
# List all stashes
git stash list
# Output:
# stash@{0}: WIP on main: 5678abc Update docs
# stash@{1}: WIP on feature: 1234def Add feature
# Show changes in most recent stash
git stash show
# Show detailed diff
git stash show -p
Stash Options
Stash with a Message
Provide a descriptive message:
git stash push -m "Work in progress on authentication"
Include Untracked Files
By default, stash ignores untracked files:
# Include untracked files
git stash -u
# or
git stash --include-untracked
Include All Files (Even Ignored)
git stash -a
# or
git stash --all
Stash Only Staged Changes
Stash what’s in the index:
Keep Index Intact
Stash working directory changes but leave staged changes:
Useful for testing staged changes before committing.
Partial Stashing
Interactively choose what to stash:
git stash -p
# or
git stash --patch
Git will ask for each hunk whether to stash it.
Managing Stashes
Applying Specific Stashes
# Apply a specific stash
git stash apply stash@{2}
# Pop a specific stash
git stash pop stash@{1}
Deleting Stashes
# Drop a specific stash
git stash drop stash@{1}
# Clear all stashes
git stash clear
git stash clear permanently deletes all stashes. They cannot be recovered through normal means.
Creating a Branch from a Stash
Apply stash to a new branch:
git stash branch new-branch-name stash@{1}
This:
- Creates a new branch from the commit where the stash was created
- Applies the stash to the new branch
- Drops the stash if successful
Common Workflows
Interrupted Work
You’re working on a feature when urgent work comes up
# Stash your current work
git stash -u -m "Feature X in progress"
Switch to the urgent task
git checkout main
# Fix the urgent issue
git commit -am "Fix critical bug"
git checkout feature-branch
git stash pop
Pulling with Uncommitted Changes
# Working directory is dirty
git pull
# Error: Your local changes would be overwritten
# Solution:
git stash
git pull
git stash pop
Testing Partial Changes
# You have both completed and incomplete changes
git add <completed-files>
git stash --keep-index # Stash incomplete work
# Run tests on completed changes
make test
# If tests pass, commit
git commit -m "Completed feature"
# Restore incomplete work
git stash pop
# While working, you notice and fix an unrelated issue
git add <unrelated-fix>
git stash push --staged -m "Unrelated bug fix"
# Continue with original work
# ...
# Later, apply the unrelated fix on a different branch
git checkout fix-branch
git stash pop
Advanced Usage
Stashing Specific Files
# Stash only specific files
git stash push -m "Stash config files" -- config/*.yaml
# Stash everything except certain files
git stash push -- '*.js' ':!tests/*'
Viewing Stash Contents
# Show files changed in stash
git stash show stash@{0}
# Show full diff
git stash show -p stash@{0}
# Show only untracked files in stash
git stash show --only-untracked stash@{0}
Creating a Stash Without Removing Changes
# Create stash but don't clean working directory
git stash create
# This outputs a commit hash, which you can apply later:
git stash store -m "Message" <commit-hash>
Stash Structure
A stash is represented as a commit with a special structure:
.----W (working directory changes)
/ /
----H----I (index changes)
- H is the HEAD commit when you stashed
- I records the index state
- W records the working directory state
Handling Conflicts
When applying a stash causes conflicts:
$ git stash pop
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Resolve conflicts manually
Edit files and remove conflict markers:
<<<<<<< Updated upstream
Current version
=======
Stashed version
>>>>>>> Stashed changes
If you used pop, drop the stash manually
If conflicts occur with git stash pop, the stash is NOT automatically dropped. You must drop it manually after resolving conflicts.
Export and Import Stashes
Export Stashes
# Export all stashes to a reference
git stash export --to-ref refs/stash-backup
# Export to print (for sharing)
git stash export --print
Import Stashes
# Import stashes from a commit
git stash import <commit-hash>
Recovering Dropped Stashes
If you accidentally dropped a stash:
# Find unreachable stash commits
git fsck --unreachable | grep commit | cut -d\ -f3 | \
xargs git log --merges --no-walk --grep=WIP
# Apply a recovered stash
git stash apply <commit-hash>
Stash vs. Other Approaches
| Approach | Pros | Cons |
|---|
| Stash | Quick, non-intrusive | Can be forgotten, conflicts possible |
| WIP Commit | Part of history, easy to reference | Clutters history, requires reset |
| Temporary Branch | Clean separation | More steps, branch management |
Best Practices
-
Use descriptive messages -
git stash push -m "..." helps identify stashes later
-
Don’t accumulate stashes - Apply or drop stashes regularly. More than 3-4 stashes indicates workflow issues
-
Include untracked files when needed - Use
-u to avoid losing new files
-
Prefer
pop over apply - This automatically cleans up applied stashes
-
Consider WIP commits for long-term storage - Stashes are meant to be temporary
-
Review stashes before applying - Use
git stash show -p to avoid surprises
Common Issues
Stash Not Showing All Changes
You likely have untracked files. Use:
Can’t Pop Stash Due to Conflicts
Use apply instead, resolve conflicts, then drop manually:
git stash apply
# Resolve conflicts
git stash drop
Lost a Stash After Clear
Recovery is possible but complex:
git fsck --unreachable | grep commit | cut -d\ -f3 | \
xargs git log --merges --no-walk --grep=WIP
Configuration
Useful stash configurations:
[stash]
# Show diff stats after stash show
showStat = true
# Show patch after stash show
showPatch = true
# Include untracked files by default
showIncludeUntracked = true
[alias]
# Quick stash with message
st = stash push -u -m
# List stashes with details
stashes = stash list --format='%gd: %s [%cr]'