Branching Strategies¶
Status: 🟢 Active | Owner: Engineering Enablement | Last Reviewed: 2025-Q4
Default: Trunk-Based Development¶
Trunk-Based Development (TBD) is the required branching strategy for all active product teams. Developers integrate small changes directly into the main branch (trunk) frequently — at least daily. This is the strategy most strongly correlated with high delivery performance in the DORA research.
Core Rules¶
mainis always deployable. The CI pipeline must be fully green before any change is merged. A brokenmainis the team's highest priority to fix.- Feature branches are short-lived: target < 1 day, maximum 2 days. Long-lived branches cause integration pain, merge conflicts, and delayed feedback.
- Incomplete features use feature flags to merge into trunk without exposing to users. Code ships; features activate on a schedule.
- No long-lived auxiliary branches: No
develop,staging,integration, orreleasebranches. All these patterns introduce delay and complexity without benefit.
Branch Naming Convention¶
<type>/<jira-ticket>-<short-description>
Examples:
feat/PROJ-1234-add-discount-codes
fix/PROJ-5678-correct-vat-calculation
chore/PROJ-9012-upgrade-spring-boot-3-2
docs/PROJ-3456-update-api-readme
refactor/PROJ-7890-extract-pricing-service
Allowed types: - feat — new feature - fix — bug fix - chore — maintenance, dependency updates, config changes - docs — documentation only - refactor — code restructuring without behaviour change - test — adding or updating tests - perf — performance improvement
Merge Strategy¶
All branches merge to main via Squash and Merge — producing one clean commit per feature branch. This keeps the main history readable and each commit deployable.
Exception: Large refactors with multiple coherent commits that tell a story may use Rebase and Merge if the commit history adds value.
Merge commits are prohibited on main.
Feature Flags for Incomplete Work¶
When a feature takes more than a day to complete, the correct approach is to merge the partial implementation behind a feature flag — not to keep the branch alive.
# Feature flag check — implementation ships continuously; feature activates on schedule
if feature_flags.is_enabled("new-checkout-flow", user_id=request.user_id):
return new_checkout_controller.handle(request)
else:
return legacy_checkout_controller.handle(request)
Approved feature flag tools: - LaunchDarkly (primary) - AWS AppConfig (approved for AWS-native services) - Simple database/config flags (approved for simple boolean flags with infrequent changes)
Feature flags must be: - Logged when evaluated (log.debug("Feature flag 'x' evaluated: {}", result)). - Removed within 30 days of the feature being fully rolled out. Stale flags are technical debt. - Tracked as Jira tickets for their eventual removal.
Release Branching (Regulated Products Only)¶
For products with formal release cycles or regulatory change control requirements, a controlled release branching model is permitted with explicit Architecture Team approval.
Permitted Release Model¶
main ──────────────────────────────────────►
│ │
└─ release/2025.3 ──►└─ release/2025.4
(hotfixes only) (hotfixes only)
Rules: - Feature development still happens on short-lived branches from main. - Release branches are cut from main at a designated stabilisation point. - Only hotfixes go onto release branches — never new features. - Hotfixes applied to a release branch must be cherry-picked back to main immediately. - Release branches are read-only after the release ships (no new commits; create the next release branch for the next cycle).
Protected Branch Configuration¶
Required branch protection rules on main (enforced in GitHub/GitLab):
| Rule | Setting |
|---|---|
| Require pull request before merging | ✅ Enabled |
| Required approvals | Minimum 1 (2 for critical services) |
| Dismiss stale approvals on new push | ✅ Enabled |
| Require status checks to pass | ✅ Enabled (CI pipeline, SonarQube) |
| Require branches to be up to date | ✅ Enabled |
| Restrict who can push directly | Only admins (never engineers) |
| Require signed commits | ✅ Enabled |
Branch Hygiene¶
- Delete branches after merge. GitHub/GitLab is configured to auto-delete merged branches. No exceptions — stale branches create confusion.
- Rebase before merge to resolve conflicts. Never merge
maininto your branch (merging creates a noisy history). Alwaysgit rebase origin/main. - Branches older than 3 days without a merged PR will be flagged in the weekly
#engineeringdigest.
When Not to Use TBD¶
TBD is not appropriate for:
- Open source or external contribution workflows — use fork + PR model.
- Emergency hotfixes to a release branch — apply directly to the release branch, then cherry-pick to
main.
References¶
Last reviewed: 2025-Q4 | Owner: Engineering Enablement