Files
hq/00-META/process/07-feature-branches.md
T

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.

  1. 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.
  2. Isolate each repo. One git worktree per touched repo under .work/<slug>/<repo>, branched off main:
    git worktree add .work/<slug>/<repo> -b feat/<slug> origin/main
    
    Parallel features never collide, and no shared checkout is edited.
  3. Commit as you go — locally. Increments land on the one branch. Nothing is pushed and no MR is opened mid-feature.
  4. Finish, then publish. When the whole feature is done — every repo, tests green — push every branch and open one MR per touched repo, together.
  5. Merge promptly, once approved. Every merge into main is notified and approved (ADR 0023); once it is, merge — do not leave it sitting. The branch is deleted on merge.
  6. 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 an initialization trunk.

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> and git worktree list return 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.