Git - Stashing

Intermediate

Git stash is like a temporary clipboard for your changes. It lets you quickly save uncommitted work, switch contexts, and then restore your changes later. Perfect for handling interruptions and context switching.

What is Git Stash?

Stash temporarily saves your modified files and staged changes, giving you a clean working directory. Think of it as a stack where you can:

  • Save current work without committing
  • Switch branches or pull updates
  • Return to your work exactly as you left it
  • Keep multiple stashes for different contexts
Working Directory: Modified files, staged changes
                   ↓ git stash
Stash Stack:       Saved snapshot #3 ← most recent
                   Saved snapshot #2
                   Saved snapshot #1 ← oldest
                   ↓ git stash pop
Working Directory: Restored files and staging

Basic Stash Operations

Creating Stashes

# Stash all modified and staged files
git stash

# Stash with descriptive message
git stash push -m "Work in progress on user auth"

# Modern equivalent of git stash
git stash push
Stash output:
Saved working directory and index state WIP on main: a1b2c3d Add login form

Viewing Stashes

# List all stashes
git stash list
Stash list:
stash@{0}: WIP on main: a1b2c3d Work in progress on user auth
stash@{1}: WIP on feature-ui: b2c3d4e Styling changes
stash@{2}: On main: c3d4e5f Emergency fix attempt

Restoring Stashes

# Apply most recent stash and remove it from stack
git stash pop

# Apply specific stash and remove it
git stash pop stash@{1}

# Apply stash but keep it in stack
git stash apply

# Apply specific stash but keep it
git stash apply stash@{2}

Advanced Stash Operations

Selective Stashing

# Stash only staged changes
git stash push --staged

# Stash only unstaged changes (keep staged)
git stash push --keep-index

# Stash specific files
git stash push -m "Config changes" config.js settings.json

# Interactive stashing (choose hunks)
git stash push -p

Including Untracked Files

# Stash including untracked files
git stash push -u
git stash push --include-untracked

# Stash including ignored files too
git stash push -a
git stash push --all

Managing the Stash Stack

Examining Stash Contents

# Show what's in latest stash
git stash show

# Show detailed diff of stash
git stash show -p

# Show specific stash
git stash show stash@{1} -p

# Show just file names in stash
git stash show --name-only
Stash show output:
 config.js    | 5 ++++-
 login.html   | 8 ++++++++
 styles.css   | 3 +++
 3 files changed, 15 insertions(+), 1 deletion(-)

Organizing Stashes

# Create stash with detailed message
git stash push -m "Feature X: Add validation logic and error handling"

# Create stash from specific commits (advanced)
git stash push --include-untracked -m "Clean state before merge"

Cleaning Up Stashes

# Drop specific stash
git stash drop stash@{1}

# Drop latest stash
git stash drop

# Clear all stashes
git stash clear
Warning: Dropped stashes are difficult to recover. Make sure you don't need them!

Practical Stash Workflows

Context Switching Workflow

Scenario: Working on feature when urgent bug report arrives
# Currently working on feature-branch
git status  # Shows modified files

# 1. Stash current work
git stash push -m "Feature X: halfway through validation logic"

# 2. Switch to main for bug fix
git switch main
git pull origin main

# 3. Create hotfix branch
git switch -c hotfix/urgent-bug

# 4. Fix bug and deploy
echo "bug fix" > bugfix.txt
git add bugfix.txt
git commit -m "Fix urgent production bug"
git push origin hotfix/urgent-bug

# 5. Return to feature work
git switch feature-branch
git stash pop  # Restore your work

# Continue where you left off

Experimental Code Workflow

Scenario: Try different approaches
# Try approach A
echo "approach A code" > experiment.js
git stash push -m "Approach A: using library X"

# Try approach B  
echo "approach B code" > experiment.js
git stash push -m "Approach B: custom implementation"

# Try approach C
echo "approach C code" > experiment.js

# Compare approaches
git stash show stash@{0} -p  # Approach B
git stash show stash@{1} -p  # Approach A

# Choose best approach
git stash apply stash@{1}  # Go with approach A

Pull Request Review Workflow

Scenario: Need to review PR while working
# Stash current work
git stash push -m "WIP: implementing feature Y"

# Fetch and checkout PR branch
git fetch origin pull/123/head:pr-123
git switch pr-123

# Review code, test, leave comments
# ...

# Return to your work  
git switch your-feature-branch
git stash pop

Stash Branch Operations

Creating Branch from Stash

# Create new branch from stash
git stash branch new-feature-branch

# Create branch from specific stash
git stash branch experiment-branch stash@{2}

This is useful when:

  • Stash conflicts with current branch
  • Want to continue work in separate branch
  • Experimenting with different implementations

Stash Conflicts and Resolution

When Stash Apply Conflicts

Stash conflict output:
Auto-merging config.js
CONFLICT (content): Merge conflict in config.js
The stash entry is kept in case you need it again.
Resolve stash conflicts:
# 1. Check status
git status

# 2. Edit conflicted files (remove markers)
nano config.js

# 3. Stage resolved files
git add config.js

# 4. Drop the stash (conflicts resolved)
git stash drop

Avoiding Stash Conflicts

# Check if stash will conflict before applying
git stash show -p | git apply --check

# Create branch if conflicts expected
git stash branch conflict-resolution

Advanced Stash Techniques

Partial Stash Application

# Apply only specific files from stash
git checkout stash@{0} -- filename.txt

# Apply stash changes interactively
git stash apply --index stash@{0}

Stash Inspection and Debugging

# Show stash as patch
git stash show -p stash@{1} > stash-patch.txt

# Apply patch manually
git apply stash-patch.txt

# Show stash statistics
git stash show --stat

Stash and Rebase

# Common workflow: stash, rebase, pop
git stash push -m "Before rebase"
git rebase main
git stash pop

# If rebase conflicts, deal with stash after
git rebase main
# Resolve rebase conflicts first
git stash pop  # May have conflicts too

Stash Best Practices

Naming and Organization

# Use descriptive messages
git stash push -m "Feature X: validation logic before refactor"
git stash push -m "Bug fix attempt #2 - trying different approach"
git stash push -m "Experimental: performance optimization"

# Include context
git stash push -m "$(git branch --show-current): $(date) - work in progress"

Regular Cleanup

# Review old stashes periodically
git stash list

# Clean up stashes older than 30 days
git stash list | grep -v "$(date -d '30 days ago' '+%Y-%m-%d')" | cut -d: -f1 | xargs -r git stash drop

Stash Safety

  • ✅ Use descriptive messages for stashes
  • ✅ Don't keep stashes forever
  • ✅ Review stash contents before applying
  • ✅ Use git stash apply instead of pop for safety
  • ❌ Don't stash critical changes long-term

Troubleshooting Stash Issues

Recovering Dropped Stashes

# Find dropped stash in reflog
git fsck --unreachable | grep commit | cut -d' ' -f3 | xargs git log --merges --no-walk --grep=WIP

# Or check stash reflog
git log --graph --oneline --all $(git fsck --no-reflog | awk '/dangling commit/ {print $3}')

Stash Performance Issues

# Large repositories: stash specific paths
git stash push -m "Only important changes" src/ docs/

# Avoid stashing large binary files
echo "*.bin" >> .gitignore

Stash Automation

Stash Aliases

# Useful stash aliases
git config --global alias.save "stash push"
git config --global alias.pop "stash pop"  
git config --global alias.list "stash list"
git config --global alias.show "stash show -p"

# Advanced aliases
git config --global alias.snapshot '!git stash push -m "snapshot: $(date)" && git stash apply "stash@{0}"'

Pre-commit Hook with Stash

# .git/hooks/pre-commit
#!/bin/sh
# Stash unstaged changes during commit
git stash push --keep-index -m "Unstaged changes during commit"

# Run tests on staged changes only
npm test

# Pop stash after commit
git stash pop

Summary

You now understand Git stashing:

  • git stash temporarily saves uncommitted changes
  • ✅ Stash stack allows multiple saved states
  • git stash pop restores and removes stash
  • git stash apply restores but keeps stash
  • ✅ Selective stashing with files, hunks, or staging states
  • ✅ Stash branches help with conflicts
  • ✅ Regular cleanup prevents stash accumulation

Next Steps

Now that you can stash changes, let's learn about recovering lost work and using reflog:

Git - Reflog & Recovery

Practice Tip: Use stash in your daily workflow when switching contexts. It's much better than making "WIP" commits that clutter history.