ADR 0017: Branch Naming and Repository Workflow
Ratification
Adopted before ADR 0018. There was no separate ratification process. Git history for this file on main is the record.
- Discussion Issue: not recorded (before ADR 0018)
- Merge PR: see git history for this file
- Accepted: as merged to
main
Context
Why this matters: Branch names are metadata. Prefixes like feature/ and
fix/ make dashboards and release tooling scannable. A single integration branch (main)
that stays green keeps trunk-based habits simple for small teams—without heavy GitFlow ceremony.
Documenting tags, semver, and rare hotfix forward-ports avoids “we only did that once in Slack” knowledge loss.
Decision
Integration branch
-
mainis the default integration branch: it should remain releasable (quality gates green on the latest commit). Feature work lands via pull request intomainunless a rare exception is agreed (hotfix branch policy below).
Branch naming
Use lowercase ASCII, hyphens as separators, and a short type prefix:
| Prefix | Use for | Example |
|---|---|---|
feature/ |
New behavior, API additions, user-visible changes. | feature/user-export-csv |
fix/ |
Bug fixes and regressions. | fix/idempotency-409-body |
docs/ |
Documentation-only changes under docs/, README, ADRs. |
docs/adr-0017-branches |
chore/ |
Tooling, CI, formatting sweeps, dependencies without product behavior change. | chore/bump-ruff |
refactor/ |
Internal restructuring without intended behavior change (still covered by tests). | refactor/user-service-split |
Optional: suffix or segment with an issue tracker id if the team uses one, e.g.
feature/42-export-csv or fix/gh-12-rate-limit. Avoid spaces, underscores except when
matching an external id, and very long names—keep the slug readable in Git UI and terminal tabs.
Lifespan and updates
- Prefer one logical change set per branch per PR when practical; split unrelated edits.
- Keep the branch reasonably current with
mainusing rebase or merge frommainbefore merge; choose one style per PR and avoid mixing noisy merge commits unless the team standardizes on merge commits for traceability. - After the PR merges, delete the remote feature branch when Git hosting offers it, to reduce clutter (local branches may be deleted by the author).
Releases and tags
- Release versions follow Semantic Versioning as already stated in
CHANGELOG.md(see ADR 0013). - Git tags for releases use the form
vMAJOR.MINOR.PATCH(e.g.v1.2.0), created on the commit that corresponds to the released changelog section.
Hotfixes
If a production fix must ship without taking everything on main, branch from the tagged release
(e.g. fix/prod-1-1-2-null-deref), fix, tag a patch, and forward-port the same commit to
main (or cherry-pick) so drift does not accumulate. This is exceptional; default flow remains
PR → main → release.
Scope
- In scope: naming, integration model, tags, contributor expectations.
- Out of scope: Git hosting UI settings (branch protection rules), required reviewers—configure per org policy.
Alternatives considered
-
Free-form branch names only.
- Pros: zero rules.
- Cons: hard to scan history and to automate changelog or CI by prefix.
-
GitFlow with long-lived
develop.- Pros: strict staging.
- Cons: extra overhead for a small service repo;
main-as-trunk is enough with strong CI.
Consequences
Positive
- Consistent names in PR lists and local
git branchoutput. - Clear place to document hotfix and tagging expectations next to changelog policy.
Trade-offs
- Existing branches keep their names until closed; rename is optional when touching an old branch.
Page history
| Date | Change | Author |
|---|---|---|
| Added Page history section (repository baseline). | Ivan Boyarkin |