For the longest time, my git stash workflow consisted of exactly two commands: git stash and git stash apply. Push changes onto the pile, pop them off later. Simple enough.

Then one day I ran git stash list and discovered I had 47 stashes dating back months. Some of them probably contained work I’d completely forgotten about. That was the day I decided to actually learn how stash works.

Beyond Push and Pop

Let’s start with something that would have saved me from my 47-stash nightmare - naming your stashes:

git stash push -m "WIP: user authentication refactor"

Now when you run git stash list, you’ll actually know what each stash contains:

stash@{0}: On main: WIP: user authentication refactor
stash@{1}: On feature-branch: debugging that weird timeout
stash@{2}: WIP on main: 3a4b5c6 some commit message

Much better than trying to remember what stash@{12} was supposed to be.

Note: If you’re on an older version of Git, you might need to use git stash save "message" instead, but this has been deprecated in favor of push -m

Pop vs Apply

I used git stash apply exclusively for years without realizing there was an alternative. The difference is subtle but important:

  • git stash pop applies the stash and then deletes it
  • git stash apply applies the stash but keeps it in the list

Why would you want to keep the stash around? I’ve found it useful when I need to apply the same changes to multiple branches:

git stash apply stash@{0}
# do some work, commit
git checkout other-branch
git stash apply stash@{0}
# same changes, different branch
git stash drop stash@{0}  # clean up when done

Stashing Specific Files

This one was a game changer for me. You don’t have to stash everything - you can be selective:

# Stash only specific files
git stash push -m "just the config changes" config.yml settings.json

# Or use patch mode to stash specific hunks
git stash push -p

The -p flag is particularly useful when you’ve made a bunch of changes but only want to stash some of them. Git will walk you through each hunk and ask if you want to stash it.

Peeking at Stash Contents

Before blindly applying a stash, you might want to see what’s actually in it:

# Show a summary of changes
git stash show stash@{0}

# Show the full diff
git stash show -p stash@{0}

I can’t count the number of times this has saved me from applying the wrong stash and creating a mess.

The Nuclear Option: Stash Branch

Here’s a feature I didn’t know existed until recently. If you’ve got a stash that’s old enough that applying it would cause conflicts, you can create a new branch from it:

git stash branch new-feature-branch stash@{2}

This creates a new branch starting from the commit where you originally created the stash, applies the stashed changes, and then drops the stash. It’s basically a time machine for your forgotten work.

Don’t Forget Untracked Files

By default, git stash only stashes tracked files. If you’ve created new files that aren’t staged, they’ll be left behind:

# Include untracked files
git stash push -u -m "including new files"

# Include untracked AND ignored files (use sparingly)
git stash push -a -m "everything, even node_modules"

Note: Be careful with -a. Stashing ignored files like node_modules will make for a very large stash

Conclusion

Git stash went from being this thing I used reflexively to something I actually think about. The ability to name stashes, selectively stash files, and peek at contents before applying has made my workflow significantly less chaotic.

And if you’re sitting on a pile of unnamed stashes right now, maybe take a few minutes to clean house. Future you will appreciate it.

# Clear all stashes (careful with this one)
git stash clear

# Or drop them one by one after reviewing
git stash show -p stash@{0}
git stash drop stash@{0}