Skip to content

Branch Strategy

martyy-code edited this page Aug 5, 2026 · 1 revision

Last synced from docs/engineering/process/branch-strategy.md on 2026-08-05. The repo file is the source of truth. If the two diverge, follow the repo.

This page explains the branch strategy used by @deessejs/fp: what each branch is for, who protects what, and who reviews what. It is conceptual, not operational: there are no shell commands here. The operational details live in the Release Process, Hotfix Flow, and Canary Snapshots pages.

Outline

  1. The branch model
  2. What each branch is for
  3. Who protects what
  4. Who reviews what
  5. The flow
  6. Why this model
  7. Related documents

1. The branch model

The repository uses three long-lived branches:

main   <- staging <- dev (conceptual)
────      ───────      ───
stable    integration  work-in-progress
  • main is the source of truth. Every commit on main is either a published version or about to be one.
  • staging is the integration branch. Most pull requests target staging. Merging to staging does not publish; it accumulates changes until a release is cut.
  • dev is a conceptual name for the collective per-feature work-in-progress. It is not materialized as a long-lived branch. Feature branches (feature/*) and fix branches (fix/*) target staging directly.

The main <- staging <- dev model is a conceptual hierarchy, not a strict data-flow rule. Code flows from feature branches to staging, then to main via the Version Packages PR. Hotfix branches skip staging and target main directly.

2. What each branch is for

main

  • Holds the latest published version of @deessejs/fp.
  • Receives two kinds of merges: the Version Packages PR (from staging) and hotfix PRs (from hotfix/* branches).
  • Every push to main triggers the Release Process. A push that introduces a Changeset file publishes a new version. A push that does not introduces a Changeset produces no release (the workflow detects and skips).
  • Protected by GitHub branch protection: PR required, no direct push, no bypass.

staging

  • Holds the integration of all in-flight changes.
  • Receives merges from feature/*, fix/*, and follow-up PRs (for hotfixes).
  • Does not trigger the release workflow on its own.
  • A Version Packages PR is opened (or updated) automatically by changesets/action against main whenever staging accumulates changes.
  • Protected by GitHub branch protection: PR required, no direct push, no bypass. Branch protection will also require the changeset-check CI job once #389 lands.

dev (conceptual)

  • Not a long-lived branch. The name refers to the collective set of feature branches, fix branches, and WIP work that has not yet been merged.
  • In the senior plan, dev is preserved as a conceptual placeholder. The feature/* and fix/* branches target staging directly. This avoids the operational cost of a third long-lived branch that would need its own protection rules and its own CI runs.
  • If a project needs a long-lived dev (for very long-lived experiments, for example), the model extends naturally: dev becomes a real branch, feature branches target dev first, then a merge from dev to staging aggregates before the release.

Short-lived branches

  • feature/* — new features. Targets staging. Created from staging.
  • fix/* — bug fixes. Targets staging. Created from staging.
  • hotfix/* — urgent fixes. Targets main directly. Created from main.

3. Who protects what

GitHub branch protection is configured at the repository level. The current rules:

Branch Required PR Required reviews Required status checks Direct push allowed
main yes 1+ (none currently) no
staging yes 1+ (none currently; changeset-check planned per #389) no
dev n/a n/a n/a n/a (does not exist)
hotfix/* yes 1+ (smaller reviewer pool from hotfix environment) per workflow no
feature/*, fix/* optional optional optional yes (for maintainers)

The release GitHub environment is the human gate for any workflow that publishes to npm. The hotfix environment (target architecture) is a separate, faster gate for hotfix PRs targeting main directly.

4. Who reviews what

Type of PR Target Required reviewer count Reviewer pool
Feature PR staging 1 any maintainer
Fix PR staging 1 any maintainer
Follow-up PR (after a hotfix) staging 1 any maintainer
Hotfix PR main 1 smaller pool, faster SLA
Version Packages PR (auto-generated) main 1 any maintainer

For a single-maintainer project, the reviewer pool is "the maintainer" — there is no team review. The model extends naturally when the project gains more maintainers: add them as CODEOWNERS or as required reviewers in the branch protection rules.

5. The flow

feature/*  ──►  staging  ──►  Version Packages PR  ──►  main
                                                            │
                                                            ▼
                                                       publish.yml
                                                            │
                                                            ▼
                                                         npm + tag

hotfix/*  ────────────────────────────────────────────────►  main
                                                            │
                                                            ▼
                                                       publish.yml
                                                            │
                                                            ▼
                                                    follow-up PR ─► staging

6. Why this model

Three reasons the model is what it is:

  • Separation of integration and release. staging accumulates changes without publishing. main only receives changes when a release is ready. This means every commit on main corresponds to a published version (or a documented failure), and no commit on main is invisible to the release tooling.
  • Hotfix escape hatch. Hotfix branches skip staging because staging may contain unfinished work that should not ship. This is the one exception to the "PRs target staging" rule.
  • No dev long-lived branch. The cost of a third long-lived branch (its own protection rules, its own CI, the risk of drift between dev and staging) outweighs the benefit for a single-package, single-maintainer project. The feature branches collectively play the role of dev.

7. Related documents

Clone this wiki locally