Git

Git Stash

Complete guide to Git stash - understanding, workflows, and best practices.

https://git-scm.com/book/en/v2

What is Git Stash?

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:

  1. Saves your modified tracked files and staged changes
  2. Records them on a stack of unfinished changes
  3. Reverts your working directory to a clean state (matching HEAD)
  4. Allows you to retrieve these changes later

Critical caveat: By default, stash does NOT include untracked files or ignored files. You must use specific flags to include them.


Why Use Git Stash?

1. Switch Branches Quickly

Need to switch branches but aren't ready to commit your current work? Stash it and retrieve it later.

2. Handle Interruptions

When urgent bug fixes or meetings interrupt your work, stash lets you save your progress without creating messy "WIP" commits.

3. Experiment Safely

Try different approaches by stashing your current attempt, testing alternatives, and retrieving or discarding as needed.

4. Clean Working Directory

Some Git operations require a clean working directory. Stash provides a quick way to achieve this.

5. Apply Changes to Different Branches

Accidentally started work on the wrong branch? Stash your changes, switch branches, and apply them where they belong.

6. Test Against Clean State

Temporarily remove uncommitted changes to test if a bug exists in the committed code or only in your modifications.


How Git Stash Works

Basic Concept

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]

Common Stash Workflows

1. Basic Stash (Save and Restore)

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:

  • Modified tracked files are saved
  • Staged changes are saved
  • Working directory becomes clean
  • Untracked files remain untouched

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

2. Stash with Untracked Files

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

3. Managing Multiple Stashes

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}

4. Interactive Stash

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 hunk
  • n - Don't stash this hunk
  • q - Quit (don't stash this or remaining hunks)
  • a - Stash this and all remaining hunks
  • d - Don't stash this or remaining hunks
  • e - Manually edit the hunk
  • ? - Show help

5. Stash Specific Files

Stash 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

Viewing Stash Contents

Show Stash Summary

# 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 Detailed Stash Diff

# Show full diff of most recent stash
git stash show -p

# Show full diff of specific stash
git stash show -p stash@{2}

Stash Management Commands

Create Stash

# 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 Stash

# 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}

View Stashes

# List all stashes
git stash list

# Show stash summary
git stash show

# Show stash diff
git stash show -p

Remove Stashes

# Remove most recent stash
git stash drop

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

# Remove all stashes
git stash clear

Create Branch from Stash

# 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:

  • Applying a stash causes conflicts
  • You want to work on stashed changes in isolation

Handling Conflicts

When Applying Stash Conflicts

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

Advanced Stash Techniques

1. Stash Only Staged Changes

# 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.

2. Create Custom Stash Message

git stash push -m "Login form validation - needs testing"

Better than default "WIP on branch" messages when managing multiple stashes.

3. Stash and Immediately Apply

# Useful for cleaning up changes before pulling
git stash
git pull
git stash pop

4. Convert Stash to Patch File

# Export stash to patch file
git stash show -p stash@{0} > my-changes.patch

# Later, apply the patch
git apply my-changes.patch

Stash vs Other Git Commands

Stash vs Commit

AspectStashCommit
PermanenceTemporary storagePermanent history
VisibilityNot part of branch historyPart of branch history
Use CaseWork in progressCompleted work
SharingLocal onlyCan be pushed/shared
OrganizationStack-basedTree-based

When to Use Stash

✅ Incomplete work you'll return to soon
✅ Quick context switching
✅ Experimenting with different approaches
✅ Cleaning working directory temporarily

When to Use Commit

✅ Completed logical units of work
✅ Changes you want to share
✅ Milestones you want to preserve
✅ Work you want in project history


Common Use Cases

1. Quick Branch Switch

# You're working on feature-a
git stash
git checkout main
# Do something on main
git checkout feature-a
git stash pop

2. Pull Latest Changes

# You have uncommitted changes
git stash
git pull origin main
git stash pop
# Resolve any conflicts

3. Test Without Your Changes

# Stash to test if bug exists in clean state
git stash
# Run tests
# If bug persists, it's not your changes
git stash pop

4. Move Work to Different Branch

# Oops, started work on wrong branch
git stash
git checkout correct-branch
git stash pop

5. Clean Up Before Rebase

# Uncommitted changes block rebase
git stash
git rebase main
git stash pop

6. Save Work Before Dangerous Operation

# Safety backup before risky operation
git stash
# Try risky git operation
# If it fails:
git stash pop  # Restore your work

Stash Internals

How Git Stores Stashes

Stashes are stored as special commits in .git/refs/stash. Each stash is actually:

  • A commit for the working directory state
  • A commit for the index (staging area) state
  • A commit that ties them together

Stash structure:

         working directory changes
        /
stash commit --- index changes
        \
         base commit (HEAD when stashed)

Reflog for Stashes

Stashes use Git's reflog mechanism:

# View stash reflog
git reflog show stash

Recovery and Safety

Recover Dropped 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>

Inspect Before Applying

Always check what's in a stash before applying:

git stash show -p stash@{0}

This prevents unexpected conflicts or overwrites.


Best Practices

  1. Use descriptive messages for stashes you'll keep
    git stash push -m "Auth refactor - needs security review"
    
  2. Clean up stashes regularly
    git stash list  # Review what you have
    git stash clear  # Remove all when done
    
  3. Don't use stash as long-term storage
    • Stash is for temporary work
    • Commit if you want to preserve work permanently
  4. Use git stash pop for one-time stashes
    • Automatically removes stash after applying
    • Keeps stash stack clean
  5. Use git stash apply when reusing stashes
    • Keep stash in stack if you'll apply it multiple times
    • Manually drop when no longer needed
  6. Include untracked files when needed
    git stash -u
    
  7. Test after popping stash
    • Ensure code still works after re-applying changes
    • Watch for subtle conflicts
  8. Create branches for complex stashed work
    git stash branch new-feature
    
  9. Avoid stashing merge conflicts
    • Resolve conflicts properly instead
    • Stashing conflicts leads to confusion
  10. Don't stash and forget
    • Review stash list weekly
    • Either apply, commit, or discard old stashes

Common Pitfalls

Forgetting Stashes Exist

Problem: Accumulating dozens of old stashes

Solution: Regularly run git stash list and clean up

Stashing Untracked Files Unintentionally

Problem: New files aren't included by default

Solution: Use git stash -u when you have new files

Applying Wrong Stash

Problem: Multiple stashes, applying the wrong one

Solution: Use git stash show -p stash@{n} to verify first

Conflicts When Popping

Problem: Stash conflicts with current work

Solution: Use git stash branch to isolate conflicts

Losing Stashes

Problem: Using git stash drop or git stash clear carelessly

Solution: Review with git stash show before dropping


Quick Reference

# 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

Keyboard Shortcuts & Aliases

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 {}'"

Troubleshooting

Stash Won't Apply

# 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

Can't Switch Branches

# Error: "Your local changes would be overwritten"
git stash
git checkout other-branch

Lost Stash After Clear

# Check reflog
git reflog stash

# Or find unreachable commits
git fsck --unreachable | grep commit
git show <commit-hash>
git stash apply <commit-hash>

Conclusion

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:

  • Use stash for temporary storage of incomplete work
  • Include untracked files with -u when needed
  • Use descriptive messages for stashes you'll keep
  • Clean up regularly to avoid accumulating old stashes
  • Create branches from stashes when conflicts arise
  • Don't use stash as long-term storage - commit instead