From Branch to Release

One ticket, one branch, one pull request, merged promptly. The boring part is the point, and uncommitted changes are a small lie the project tells you.

"what is this uncommitted 42 lines"

"why are there uncommitted changes"

"push it all you know i don’t like loose ends"

Three things I typed across June, and they are more or less the same sentence three times.

I have a rhythm and it is deliberately boring. One ticket, or a small related group of tickets inside an epic, gets one branch. That branch becomes a pull request. The PR merges to main. When the epic is complete, that is a release.

The boring part is the point.

One branch per ticket means the diff is readable. If the branch contains one piece of work, I can look at the changes and tell whether they are the changes I asked for. If it contains three pieces of work, I cannot, and what actually happens is that I skim it and approve it, which is not review, it is theatre.

Merging to main promptly is what makes the deployment loop work. In my setup the host is listening for a merge to main. Code that sits on a branch is not deployed, is not tested by reality, and is quietly accumulating conflict with everything else that moved.

Releases at the epic boundary give the work a shape. Not every merge is an event. The completion of a body of work is.

And then there is the loose ends thing, which I will admit is temperamental as much as it is rational.

Uncommitted changes sitting in a working directory are a small lie the project tells you. The repository says one thing, the disk says another, and you have to hold the difference in your head. Twelve stale branches are the same lie at a larger scale: every one is either work that matters and is not merged, or work that does not matter and has not been deleted, and you cannot tell which without opening it.

On 8 July I deleted twelve feature branches in one command. Swimlanes, chapters, palette, vibe presets, brand docs, embed query params. Every one had been merged or abandoned weeks earlier. None of them were doing any harm, and clearing them out took about four seconds, and the project immediately felt like something I could see the edges of again.

That is not efficiency. It is the same instinct as putting the tools away. You cannot see the bench if the bench is covered.

One more, and it took a conversation to sort out. On 1 July I had to say plainly:

"just to be clear, i don’t merge, you do, and 99.9% of the time i just want you to merge to main"

Deciding who holds each part of the routine is worth doing explicitly. Ambiguity about who merges produces exactly the loose ends I am complaining about.

Next: the technical thing a PM now actually needs to understand, and it is not code.