2.8 KiB
Playbook 07 — Feature branches across repos
Trigger. Work that changes code — in one code repo or in several at once (mesh-sdk,
mesh-control, mesh-catalog, mesh-host, mesh-lab, and hq when a decision rides along).
Who runs it. Anyone who writes code, engineers and agents alike. Agents follow it exactly — it is the guard against the failure it was written for.
The failure it prevents
A feature was worked as a branch-and-MR per unit of thought — one per decision, one per stacked increment — and each MR was treated as finished when it was opened, not when it was merged. Across repos the same feature took a different branch name in each. The MRs piled up unmerged: one session left sixteen stacked intermediate MRs that had to be consolidated and closed by hand. An MR is a review checkpoint, not a scratchpad.
The rule
One feature is one branch name, one worktree per repo, one MR per repo, opened once, at the end.
- Name the feature once.
feat/<slug>. The same branch name in every repo the feature touches — never a different name per repo, never a fresh branch per increment within the feature. - Isolate each repo. One git worktree per touched repo under
.work/<slug>/<repo>, branched offmain:Parallel features never collide, and no shared checkout is edited.git worktree add .work/<slug>/<repo> -b feat/<slug> origin/main - Commit as you go — locally. Increments land on the one branch. Nothing is pushed and no MR is opened mid-feature.
- Finish, then publish. When the whole feature is done — every repo, tests green — push every branch and open one MR per touched repo, together.
- Merge promptly, once approved. Every merge into
mainis notified and approved (ADR 0023); once it is, merge — do not leave it sitting. The branch is deleted on merge. - Leave nothing behind. After the MRs merge, no
feat/<slug>branch and no.work/<slug>worktree survive.
What this is not
- Not a licence to batch unbounded work. A feature is a bounded unit; if it sprawls for days, end-of-feature bloat merely replaces per-increment bloat. Split it into features, each its own branch and MR.
- Not a second trunk. Every repo branches off
main. There is no longer aninitializationtrunk.
How it is checked
The end state is visible, and its absence is the smell:
- After a feature merges,
git branch -r | grep feat/<slug>andgit worktree listreturn nothing for it. A surviving branch or worktree means step 6 was skipped. - More than one open MR in a repo that share no feature name, or a stack of MRs none of which is merged, is the failure this playbook exists to prevent — stop and consolidate before opening more.