Advanced Git Stash — Partial Stashes, Branches, and Recovery
In this tutorial, you'll learn about Advanced Git Stash. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
What You'll Learn
Go beyond git stash and stash pop — use partial stashes, stash individual hunks, create branches from stashes, recover dropped stashes, and automate stash workflows in Git.
Why It Matters
Basic stash works for simple "save all, restore all" scenarios. Advanced stash techniques let you save only specific files, stash different changes to different branches, and recover from mistakes — turning stash into a precision tool.
Real-World Use
You have three unrelated changes in your working directory (a CSS tweak, a database Migration, and a bug fix). You need to stash each independently so you can open separate branches. Advanced stash makes this possible.
Partial File Stashing
Save only specific files while leaving others untouched:
# Working on login.py, style.css, and database.py
git status
# modified: login.py
# modified: style.css
# modified: database.py
# Stash only CSS and HTML files
git stash push -m "UI changes" -- *.css *.html
# Saved working directory and index state On main: UI changes
# Only login.py and database.py remain modified
git status
# modified: login.py
# modified: database.py
# Stash the database changes separately
git stash push -m "DB migration" -- database.py
# Saved working directory and index state On main: DB migration
# Now only login.py is modified
git status
# modified: login.py
Interactive Hunk Stashing
Choose which hunks to stash, hunk by hunk:
# Stash interactively
git stash push -p
# Diff divided into hunks. For each hunk:
# (1) yes / (2) no / (3) edit / (4) quit / (5) all / (6) help
# Example:
# diff --git a/login.py b/login.py
# @@ -10,5 +10,8 @@ def login():
# verify_password()
# + send_welcome_email() # ← Hunk 1
# + log_attempt() # ← Hunk 2
# Stash this hunk? [y,n,q,a,d,e,?] y # Stash hunk 1
# Stash this hunk? [y,n,q,a,d,e,?] n # Keep hunk 2 in working dir
Keep Index Stashing
Stash unstaged changes but keep staged changes intact:
# Stage some changes, leave others unstaged
git add login.py # Staged
echo "debug" >> utils.py # Unstaged
# Stash only unstaged changes
git stash push -k -m "WIP utils debug"
# --keep-index keeps staged files (login.py) in the working tree
# Only utils.py changes are stashed
git status
# modified: login.py # Still staged as before
# Restore the unstashed changes
git stash pop
# utils.py changes are back
Creating a Branch from a Stash
When a stash conflicts with the current branch state:
# Current branch has diverged since the stash was created
git stash list
# stash@{0}: WIP on feature: a1b2c3 Add login form
# Trying to pop causes conflicts
git stash pop
# CONFLICT (content): Merge conflict in login.py
# Instead, create a branch from the commit where stash was made
git stash branch new-feature stash@{0}
# Switched to a new branch 'new-feature'
# On branch new-feature
# Changes to be committed:
# modified: login.py
# The stash is automatically dropped if successful
Viewing Stash Contents
# List all stashes
git stash list
# stash@{0}: On main: DB migration
# stash@{1}: On main: UI changes
# stash@{2}: WIP on feature: a1b2c3
# Show summary of what's in a stash
git stash show stash@{1}
# style.css | 15 +++++++++++++++
# 1 file changed, 15 insertions(+)
# Show the full diff
git stash show -p stash@{1}
# Show as a patch
git stash show -v stash@{1}
Recovering Dropped Stashes
# Accidentally dropped a stash
git stash drop stash@{1}
# Dropped stash@{1} (a1b2c3d4e5f6...)
# Use reflog to find the commit
git reflog show refs/stash
# a1b2c3 refs/stash@{0}: WIP on main: UI changes
# d4e5f6 refs/stash@{1}: WIP on main: DB migration ← still in reflog
# Recover by applying the commit directly
git stash apply d4e5f6
# Changes restored as if you did git stash pop
Stashing Untracked and Ignored Files
# Default: stash only tracked, modified files
git stash
# Include untracked files (new files not yet tracked)
git stash --include-untracked # or -u
# Include everything (including .gitignore'd files)
git stash --all # or -a
# WARNING: -a stashes everything including node_modules, .env, etc.
Automated Stash Workflow
# Before switching branches, auto-stash
#!/bin/bash
# git-switch-safe: stash changes, switch branch, pop stash
BRANCH=$1
CURRENT=$(git branch --show-current)
if [ -n "$(git status --porcelain)" ]; then
git stash push -m "Auto-stash from $CURRENT"
STASHED=true
fi
git checkout "$BRANCH"
if [ "$STASHED" = true ]; then
git stash pop
fi
Common Pitfalls
| Mistake | Solution |
|---|---|
| Stash pop causes conflicts | Use git stash branch instead |
| Lost stash after drop | Check git reflog show refs/stash |
| Stashed too many changes at once | Use -p for interactive, or push -- <path> for partial |
| Untracked files missing from stash | Add -u or -a depending on need |
Practice Questions
- How do you stash only CSS files while leaving Python files in the working directory?
- What command creates a new branch from a stash that avoids conflicts?
- How can you recover a stash after running
git stash drop?
FAQs
Next Steps
After mastering advanced stash techniques, use Git Worktrees to avoid stashing entirely, or learn interactive rebase to clean up commit history before merging.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro