Stash checkpoints beat WIP commits

Mid-task, something is half-working, and I want a save point before I try something risky. The usual advice for this is to make a WIP commit and squash it later. I do not do that. I use git stash instead.

git stash push -m "before refactoring the parser"
git stash pop

That is it. A named checkpoint I can come back to, no commit in the log.

A WIP commit is essentially a promise to clean up later. I break that promise constantly, and so does everybody else I have ever worked with. The squash never happens, or it happens wrong, or I forget which commits were WIP and which were real, and now the branch history is a mix of actual work and save points that mean nothing to anybody, including me next week. Stashes do not have this problem because they live outside the branch history. When I am done, the log only contains commits that describe real changes.

How I actually use it

Permalink to “How I actually use it”

I stash before anything I am not sure about:

# about to try something
git stash push -m "working auth, before switching to JWT"

# it went badly
git stash pop

# it went well, just drop the stash
git stash drop

I stash when I need to switch branches:

git stash push -m "halfway through the migration"
git switch main
# do the hotfix
git switch feature/migration
git stash pop

I stash when I want to test the current state against a clean version:

git stash push -m "with new caching"
# run benchmarks on the old code
git stash pop
# run benchmarks on the new code

Always name your stashes

Permalink to “Always name your stashes”

git stash with no message creates entries like stash@{0}: WIP on main: a3f2b1. After two of these you have no idea which is which, useless. Always use -m:

git stash push -m "before removing the old API"
git stash list
# stash@{0}: On main: before removing the old API

Now git stash list reads like a little changelog of save points.

The distinction in my head is simple. Commits are for history, stashes are for checkpoints. Mixing those two up is how you end up with fix, fix2, wip, wip final, actually final in your git log, and none of us want to be that person.