Git Stash and Stash Management: Save Work Without Committing

Master git stash for saving uncommitted changes, named stashes, stash list management, and when to use stash vs commit in production workflows.

published: reading time: 14 min read updated: March 31, 2026

Git Stash and Stash Management: Save Work Without Committing

git stash is the command you reach for when you’re in the middle of something and need to switch contexts immediately. Maybe production is on fire and you need to pull the latest main. Maybe your code review came back and you need to switch branches. Maybe you just realized you’re on the wrong branch.

Stash saves your uncommitted changes — both staged and unstaged — onto a stack, leaving your working directory clean. You can pop them back later, apply them to a different branch, or drop them entirely. It’s Git’s answer to “I’m not ready to commit but I need a clean slate.”

This post covers the complete stash toolkit: named stashes, selective stashing, stash list management, and the scenarios where stash is the wrong tool.

When to Use / When Not to Use

Use Git Stash When

  • Context switching — You need to switch branches but have uncommitted work
  • Emergency fixes — Production is broken and you’re in the middle of a feature
  • Experimentation — You want to try something without committing to it
  • Pull rebase — You need a clean working directory for git pull --rebase
  • Code review switches — You need to check out a PR branch while working on something else

Do Not Use Git Stash When

  • Long-term storage — Stash is not a backup. Use branches for work you want to keep
  • Sharing work — Stash is local-only. Push branches to share with teammates
  • Completed features — If the work is done, commit it. Don’t stash finished code
  • Large changesets — Stashing hundreds of files is a sign you should commit more frequently

Core Concepts

Git stash operates as a stack of saved changesets:

CommandDescriptionEffect
git stashSave current changesWorking directory becomes clean
git stash listShow all stashesDisplays stash stack
git stash popApply and remove top stashRestores changes, removes from stack
git stash applyApply without removingRestores changes, keeps on stack
git stash dropRemove a stashDeletes from stack
git stash clearRemove all stashesEmpties the entire stack

Each stash is a commit-like object that stores both the working directory and the index state.

graph LR
    A[Working Directory] -->|git stash| B["stash@{0}"]
    B -->|git stash| C["stash@{1}"]
    C -->|git stash| D["stash@{2}"]
    D -->|git stash pop| E[Working Directory]

Architecture and Flow Diagram

The complete stash lifecycle from creation through application or cleanup:


graph TD
    A[Uncommitted Changes] -->|git stash| B[Stash Stack]
    B -->|git stash list| C[View Stash List]
    C -->|Decision| D{What to do?}
    D -->|Restore + Remove| E[git stash pop]
    D -->|Restore + Keep| F[git stash apply]
    D -->|Delete One| G[git stash drop]
    D -->|Delete All| H[git stash clear]
    E --> I[Clean Working Directory]
    F --> I
    G --> B
    H --> J[Empty Stack]

Step-by-Step Guide

1. Basic Stash Usage

The simplest form saves everything and cleans your working directory:


# Save all changes (staged and unstaged)
git stash

# Working directory is now clean
git status
# On branch feature/login
# nothing to commit, working tree clean

# Switch branches
git checkout main

# Do your emergency fix...
git commit -m "fix: resolve production issue"

# Return to your feature branch
git checkout feature/login

# Restore your stashed changes
git stash pop

2. Named Stashes

Give your stashes meaningful names so you can find them later:


# Stash with a message
git stash push -m "WIP: user authentication flow - 60% complete"

# Stash with a descriptive name
git stash push -m "feat: add password validation"

# List stashes with messages
git stash list
# stash@{0}: On feature/login: WIP: user authentication flow - 60% complete
# stash@{1}: On feature/login: feat: add password validation
# stash@{2}: On main: WIP: debug production memory leak

3. Selective Stashing

Stash only specific files or use the --keep-index flag:


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

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

# Stash including ignored files
git stash --all
# or
git stash -a

# Stash specific files (Git 2.13+)
git stash push -m "partial stash" -- src/auth.ts src/utils.ts

4. Managing the Stash List

Keep your stash list organized and clean:


# View all stashes
git stash list

# Apply a specific stash (by index)
git stash apply stash@{2}

# Pop a specific stash
git stash pop stash@{1}

# Drop a specific stash
git stash drop stash@{0}

# Show what's in a stash without applying
git stash show stash@{1}
# Or with full diff
git stash show -p stash@{1}

# Clear all stashes
git stash clear

5. Creating Branches from Stashes

Turn a stash into a proper branch:


# Create a branch from the latest stash
git stash branch feature/auth-from-stash

# Create a branch from a specific stash
git stash branch feature/password-validation stash@{2}

# This creates the branch, checks it out, and applies the stash
# The stash is automatically dropped after successful application

Production Failure Scenarios + Mitigations

ScenarioWhat HappensMitigation
Stash conflict on popThe codebase changed since stashing, causing conflictsResolve conflicts like a merge conflict; use git stash show -p to review before popping
Stash lossgit stash clear or accidental drop removes workStash is stored as commits — use git reflog to recover lost stashes
Stash stack overflowDozens of unnamed stashes become unmanageableName every stash; review and clean stash list weekly
Stash on wrong branchStashed changes don’t apply cleanly to the target branchUse git stash branch to create a new branch from the stash
Untracked files lostgit stash without -u doesn’t save untracked filesAlways use git stash -u if you have new files
Stash as permanent storageWork sits in stash for weeksStash is local and fragile; use branches for anything you want to keep

Trade-offs

AspectAdvantageDisadvantage
SpeedInstant context switch without commitChanges are not shared with team
FlexibilityCan apply to any branchConflicts if target branch diverged
OrganizationNamed stashes with messagesStack can become cluttered over time
Safety — Changes are saved as commitsRecoverable via reflog if accidentally droppedNot visible in normal git log
Local-onlyNo remote pollutionWork is lost if disk fails
Selective stashingStash only what you needComplex syntax for partial stashes

Implementation Snippets

Stash Alias Configuration


# Add to ~/.gitconfig
[alias]
    st = status
    sl = stash list
    sp = stash pop
    sa = stash apply
    sd = stash drop
    ss = stash show
    sn = "!f() { git stash push -m \"$*\"; }; f"
    sc = stash clear
    sb = "!f() { git stash branch \"$1\" \"${2:-stash@{0}}\"; }; f"

Stash Review Script


#!/bin/bash
# scripts/review-stash.sh
# Review all stashes and decide what to keep

echo "=== Stash Review ==="
echo ""

git stash list | while IFS=: read -r ref message; do
  echo "--- $ref ---"
  echo "Message:$message"
  echo "Files changed:"
  git stash show --stat "$ref" 2>/dev/null
  echo ""
  echo "Apply this stash? (y/n/d for drop)"
  read -r action
  case $action in
    y) git stash apply "$ref" ;;
    d) git stash drop "$ref" ;;
    *) echo "Skipped" ;;
  esac
  echo ""
done

Pre-switch Hook — Auto-Stash


#!/bin/bash
# scripts/auto-stash-switch.sh
# Automatically stash before switching branches

BRANCH=$1

if [ -z "$BRANCH" ]; then
  echo "Usage: auto-stash-switch.sh <branch>"
  exit 1
fi

# Check for uncommitted changes
if ! git diff --quiet || ! git diff --cached --quiet; then
  echo "Uncommitted changes detected. Stashing..."
  git stash push -m "Auto-stash before switching to $BRANCH"
  git checkout "$BRANCH"
  echo "Switched to $BRANCH. Changes stashed."
  echo "Run 'git stash pop' when ready to restore."
else
  git checkout "$BRANCH"
  echo "Switched to $BRANCH (no changes to stash)."
fi

Stash Age Monitor


#!/bin/bash
# scripts/stash-age-check.sh
# Warn about stashes older than 7 days

MAX_AGE_DAYS=7
THRESHOLD=$(date -d "$MAX_AGE_DAYS days ago" +%s 2>/dev/null || date -v-"${MAX_AGE_DAYS}d" +%s)

echo "=== Stash Age Report ==="
echo ""

git stash list --format='%gd %gs' | while read -r ref message; do
  # Get the commit date of the stash
  STASH_DATE=$(git log -1 --format='%ct' "$ref" 2>/dev/null)
  if [ -n "$STASH_DATE" ] && [ "$STASH_DATE" -lt "$THRESHOLD" ]; then
    echo "WARNING: $ref is older than $MAX_AGE_DAYS days"
    echo "  Message: $message"
    echo ""
  fi
done

Observability Checklist

  • Logs: Not typically applicable — stash is a local operation
  • Metrics: Track stash frequency per developer (high frequency may indicate commit discipline issues)
  • Alerts: Alert when stash count exceeds 10 per developer or stashes older than 7 days exist
  • Dashboards: Display stash count, average stash age, and stash-to-branch conversion rate
  • Code Review: Check for stashed work during code reviews — stashed code should be committed or discarded

Security and Compliance Notes

  • Local-only: Stash data never leaves your machine — it’s stored in .git/refs/stash
  • No audit trail: Stash operations are not visible in remote logs or PR history
  • Compliance gap: For regulated environments, all code changes should be committed and reviewed — stash bypasses this
  • Data sensitivity: Stashed changes may contain sensitive data (API keys, credentials) — never stash secrets
  • Recovery: Lost stashes can be recovered via git reflog within the reflog retention period

Common Pitfalls and Anti-Patterns

  1. The Stash Graveyard — Dozens of unnamed stashes accumulate over months. Name every stash and clean up weekly.
  2. Stash as Commit Substitute — Using stash instead of committing finished work loses history and prevents code review.
  3. Pop Without Checking — Popping a stash onto the wrong branch creates conflicts. Always verify your branch before popping.
  4. Ignoring Untracked Filesgit stash without -u leaves new files behind, causing confusion when you return.
  5. Stash Sharing Myth — Stash is local-only. You cannot share stashes with teammates. Use branches for shared work.
  6. Conflict Resolution Failure — When stash pop conflicts, the stash is NOT removed. You must resolve conflicts and then git stash drop.
  7. Stashing Secrets — Stashed changes may contain hardcoded credentials. Always check what you’re stashing.

Quick Recap Checklist

  • Use git stash for temporary context switching, not long-term storage
  • Name every stash with git stash push -m "description"
  • Use git stash -u to include untracked files
  • Review stash list regularly and clean up old stashes
  • Use git stash show -p to review contents before applying
  • Use git stash branch to convert stashes to proper branches
  • Never stash secrets or sensitive data
  • Resolve conflicts after git stash pop before dropping the stash
  • Keep stash count under 10 per developer
  • Commit finished work instead of stashing it

Stash vs Commit vs Worktree

AspectStashCommitWorktree
PersistenceLocal, fragile, expiresPermanent in historyPermanent, independent
ShareabilityCannot be sharedPushed to remoteEach worktree is local
RecoveryVia reflog if droppedAlways recoverableN/A — files are on disk
Use caseQuick context switchCompleted or checkpointed workParallel branch work
Disk overheadMinimal (one object)Minimal (one object)Full working directory copy
VisibilityHidden from git logVisible in git logVisible via git worktree list
Best forHours of work, local onlyAnything worth keepingDays of parallel development

Stash Hygiene Checklist

  • Name every stashgit stash push -m "descriptive message"
  • Apply promptly — Don’t let stashes sit for more than a few days
  • Review before applyinggit stash show -p stash@{n} to confirm contents
  • Drop after applying — Use pop instead of apply unless you need to keep it
  • Weekly cleanup — Run git stash list and drop anything older than a week
  • Convert old stashes — Use git stash branch <name> for stashes you still need
  • Never stash secrets — Check for credentials before stashing
  • Include untracked files — Use -u flag when you have new files
  • Keep count under 10 — More than 10 stashes means you’re using stash wrong
  • Document stash purpose — If you can’t explain why it’s stashed, drop it

Interview Q&A

What is the difference between git stash pop and git stash apply?

git stash pop applies the stash and removes it from the stash stack. If there are conflicts, the stash remains on the stack so you can retry after resolving.

git stash apply applies the stash without removing it from the stack. This is useful when you want to apply the same stash to multiple branches or keep it as a backup.

In practice, use pop for the common case and apply when you need to preserve the stash.

How do you recover a dropped or lost stash?

Stashes are stored as commits, so they appear in the reflog. To recover a lost stash:

  1. Run git reflog to find the stash commit
  2. Look for entries like stash@{0} or WIP on branch
  3. Note the commit SHA
  4. Run git stash apply <sha> to restore it

This works as long as the reflog hasn't been pruned (default retention is 90 days).

When should you use a branch instead of a stash?

Use a branch when the work is complete enough to commit, when you need to share it with teammates, or when you want it to appear in the project history. Branches are visible, shareable, and permanent.

Use a stash when you need a quick context switch, when the work is too incomplete to commit meaningfully, or when you're experimenting and aren't sure if the changes are worth keeping.

Rule of thumb: if you'd be upset losing the work, it belongs on a branch, not in a stash.

Can you stash changes from only some files?

Yes, since Git 2.13, you can stash specific files:

git stash push -m "partial stash" -- src/auth.ts src/utils.ts

Alternatively, use --keep-index to stash only unstaged changes while keeping staged changes in the working directory. Or use git stash --patch (or git stash -p) to interactively select which hunks to stash, similar to git add -p.

Resources

Category

Related Posts

Git Worktree for Parallel Work: Multiple Branches Simultaneously

Master git worktree to work on multiple branches simultaneously without stashing or cloning. Learn parallel development workflows, management commands, and best practices.

#git #version-control #git-worktree

Master git add: Selective Staging, Patch Mode, and Staging Strategies

Master git add including selective staging, interactive mode, patch mode, and staging strategies for clean atomic commits in version control.

#git #staging #git-add

Git Aliases and Custom Commands: Productivity Through Automation

Create powerful Git aliases, custom scripts, and command extensions. Learn git extras, shell function integration, and team-wide alias standardization for faster workflows.

#git #version-control #aliases