Skip to content

Branching and Merging#

How changes move from a working branch into a protected branch. The model is small branches, pull-request-only integration, and a history that stays readable.

Topic branches#

  • Work happens on short-lived branches cut from the default branch — one per issue. Each gets its own worktree.
  • Name branches <type>/<issue>-<short-slug>, e.g. feat/42-pagination or fix/99-null-context. The type matches the change type.
  • Branches stay short-lived. The longer a branch lives, the further it diverges and the harder it is to merge.

Pull requests only#

  • Protected branches are never pushed to directly. Every change arrives through a pull request — even a one-line fix.
  • A pull request is green before review begins. Automated checks run first, so reviewers spend their attention on judgment rather than on catching what CI catches. This is shift left.
  • Keep pull requests small and focused: one deliverable, reviewable in a single pass.

Merge models#

Two models, chosen by the repository's deployment shape:

  • Single-branch (trunk). One protected branch, always deployable. Topic branches squash-merge into it for a linear history. Suited to applications and libraries that release from the trunk.
  • Promotion (multi-environment). Changes flow through environment branches (for example devmain), each promotion gated by an approval. Suited to infrastructure where environments deploy in sequence.

The choice follows from repository segmentation: an app and an infrastructure stack don't share a model.

A readable history#

  • Squash-merge a topic branch so each merged change is one coherent commit on the protected branch.
  • Delete branches after merge. Stale branches are noise.
  • Commit messages are direct and descriptive. See Commit Conventions.