Skip to content

git stash advanced: CI-Safe Stash Patterns for DevOps Engineers

git stash is more than a quick "shelve my changes" shortcut. When you're juggling CI pipelines, hotfix branches, and feature branches simultaneously, the right stash pattern prevents lost work and merge noise.


Quick Reference Cheat Sheet

Action Command When to Use
Save all changes git stash Switch branches or pause for CI run
Save changes, keep index git stash --keep-index When you want git stash pop to restore the staged state
Save changes for specific paths git stash push -- <path1> <path2> Only stash modified files; leave README.md alone
List all stashes git stash list See what's been saved across sessions
Show a stash's diff git stash show -p stash@{2} Preview what a stash contains
Drop a stash git stash drop stash@{1} Remove an unwanted stash
Drop all stashes git stash clear Clean the slate entirely
Apply without removing git stash apply Re-apply the same stash from multiple branches
Create branch from stash git stash branch <new-branch> Turn a stashed change set into its own branch
Stash only tracked files git stash --patch / git stash -p Interactively choose hunks
Stash untracked files git stash -u or git stash -a Include new, untracked files

stash pop vs stash apply: Why It Matters

  • git stash pop = git stash apply + git drop the stash entry. Once popped, it's gone.
  • git stash apply = re-apply the stash without removing it. Use when you want to:
  • Apply the same stash to two different branches
  • Re-apply after a pop failed part-way through

Pro tip: If stash pop leaves conflict markers, run git stash apply instead to keep the stash available while you resolve.


Stashing Specific Paths (Selective Stash)

# Stash only changes to src/components/Button.js
git stash push -- src/components/Button.js

# Stash everything *except* config files
git stash push -- '--' ':!(*)config*'

# Interactively choose hunks
git stash -p

CI Pattern: When a CI job starts pulling in new dependencies or changing lockfiles, selectively stash only the files you're actively working on, leaving package-lock.json or poetry.lock untouched.


git stash branch: Turning a Stash into a Branch

# Create a new branch from the current state, apply the stash, and drop the stash
git stash branch hotfix-stash main

This checks out main, applies the stashed changes there, and drops the stash. Ideal when you stash work on feature-A but need to pivot to a production hotfix immediately.


CI-Safe Stash Workflow Pattern

# 1. Before switching to a branch for a quick test
git stash -- "src/*.js"

# 2. Run the CI check on the clean branch
./ci-run-tests.sh

# 3. Re-apply the stash after CI completes
git stash pop

If the pop conflicts, fall back to:

git stash apply
# resolve conflicts manually
git stash drop  # only after you've verified the result

Common Pitfalls & Fixes

Problem Fix
stash pop fails with "untracked files would be overwritten" Use git stash apply first, then git stash drop; or git clean -fd before popping
"You cannot stash untracked files without -u/-a" Always use git stash -u when you have new files you want preserved
Accidentally stashed changes you needed git stash list → find the ref → git stash drop stash@{N} or git stash apply stash@{N}
Losing staged changes after stash pop Use git stash --keep-index on stash, or git reset --staged after popping

Recipe: Preserve the Index on stash pop

# Stash with index marker so `pop` restores staging state
git stash --keep-index

# ... switch branches, run CI, etc.

# Pop restores both the working tree changes AND the staging area
git stash pop

This is invaluable when your CI pipeline expects certain files to be committed (e.g., npm install producing package-lock.json that should be staged) but you need to switch contexts temporarily.


Advanced: Stash Management Script

A helper script (scripts/stash-manage.sh) is provided to:

  • List stashes with file counts
  • Apply a specific stash by index
  • Drop all stashes older than N days
  • Export/import stash to file for long-term preservation in CI environments