Skip to content

Branch Protections

main is the only long-lived code branch. Work happens on short-lived branches, merges through PR review, and promotes through tags and values files instead of environment branches.

Rules that matter

RuleWhy it exists
Protect mainKeeps the deployment baseline controlled
Block direct pushesForces review, checks, and audit metadata
Require at least one approvalCreates separation of duties
Dismiss stale reviewsPrevents old approvals from covering new code
Require conversation resolutionKeeps review concerns visible
Enforce squash-only linear historyMakes one PR equal one revertible commit
Enforce branch-name and commit conventionsKeeps automation and audit search reliable
Require signed commits where policy demands itTies sensitive changes to verified actors

Branch names

Use prefix/short-kebab-slug.

PrefixUse forExample
feat/New user-visible behaviorfeat/language-selector
fix/Bug fixes and remediationfix/duplicate-submission
security/Auth, secrets, hardening, vulnerability fixessecurity/rotate-signing-key
infra/Helm, ArgoCD, Kubernetes, cloud, runnersinfra/preview-namespaces
ci/GitHub Actions, checks, release automationci/add-commitlint-check
build/Build system and packagingbuild/container-cache
docs/Documentation-only changesdocs/gitops-branch-rules
test/Test-only changestest/add-profile-regression
refactor/Behavior-preserving structure changesrefactor/form-state
perf/Performance improvementsperf/query-cache
style/Formatting and style-only changesstyle/lint-cleanup
revert/Reverting a prior changerevert/bad-cache-change
chore/Routine maintenancechore/update-dependencies

Emergency work still uses fix/ or revert/ plus an incident reference in the PR. There is no hotfix/ or emergency/ prefix because those imply a second path around normal controls.

What to avoid

AvoidUse instead
Long-lived staging or prod branchesPromote tags or values-file changes
Week-long WIP branchesSplit the work and merge behind a flag
Direct emergency pushes to mainOpen an emergency PR and use the override path if needed
Branch names like updates or miscUse a prefix that says what kind of review is needed
Hiding broken code behind a flagFix the code before merge

Feature flags

Use a feature flag when code is safe to deploy but behavior is not ready to expose. The hidden path still needs tests, review, and a cleanup owner. The detailed flag standard lives in Deployments.

Enforcement

GitHub governance is declarative state. The scripts under templates/governance/ define the desired organization and repository policy; validation reports drift when GitHub no longer matches those scripts.

Branch policy is enforced by organization rulesets:

  • branch-protections targets default branches, blocks deletion and force-pushes, requires linear history, and allows only squash merges.
  • conventional-branch-names targets all branches and requires the approved prefix plus lowercase slug.
  • code-review requires PRs, code-owner review where configured, stale review dismissal, and conversation resolution.
  • release-tags allows only approved SemVer, beta, and release-candidate tag shapes.

Run apply, then validate. Do not repair drift by clicking through the GitHub UI unless the script is updated in the same change.

Run or inspect the scripts:

Terminal window
ORG=mdds bash templates/governance/enforce-branch-protections.sh
ORG=mdds bash templates/governance/enforce-branch-names.sh
task governance:apply:org ORG=mdds
task governance:validate ORG=mdds
task governance:apply:repo ORG=mdds REPO=my-repo
task governance:validate ORG=mdds REPO=my-repo

Governance apply order

  1. Create governance teams.
  2. Apply org settings and Actions defaults.
  3. Define custom properties.
  4. Apply code-review rules.
  5. Apply branch protections.
  6. Apply optional deploy gates.
  7. Enable reusable workflow sharing.
  8. Deploy and require the admin governance workflow.
  9. Apply restricted-data controls.
  10. Apply branch-name, commit-message, and release-tag rules.
  11. Apply repo-scoped controls where required.

Teams run first because rulesets and production environments reference team IDs. Mainline branch protections have no bypass actors; convention rules have no bypass actors.

Governance controls

ControlScopeWhat it prevents
Required PRs and code-owner reviewDefault branchesDirect mainline writes and unreviewed owned-path changes
Stale review dismissal and thread resolutionDefault branchesOld approvals carrying unrelated later changes
Squash-only merges and linear historyDefault branchesNoisy release history and hard-to-revert merge bubbles
Branch deletion, force-push, and signed-commit rulesDefault branchesLoss of audit history and unverified authorship
Central governance workflowDefault branchesPR titles or shared checks bypassing the release grammar
Conventional branch names and commitsBranches and commitsAmbiguous branch and changelog metadata
Release tag namingTagsAmbiguous production promotion targets
Restricted-data rulesRestricted repositoriesBaseline-only controls on high-risk repositories
Production environment approvalRepository prod environmentOne-person production promotion
Incident priority labelsRepository labelsInconsistent incident language

Runtime knobs

VariableUse
ORG / GITHUB_ORGTarget organization for every governance task
REPOTarget repository for repo-scoped tasks
ADMIN_REPORepository that hosts the central governance workflow
GOVERNANCE_WORKFLOW_PATH / GOVERNANCE_WORKFLOW_REFRequired workflow location
REQUIRED_STATUS_CHECKSOptional deploy-gate checks
RULESET_BYPASS_TEAMEmergency bypass team, normally technical-owners
PROD_REVIEWER_TEAMSTeams that approve protected production deployments
COMPLIANCE_REPORT_PATHJSON evidence export from validation

Bypass policy

technical-owners may bypass only selected review, workflow, restricted-data, deploy-gate, and release-tag rules for emergency unblock. They cannot bypass direct mainline write protections, branch naming, or commit-message rules. Every bypass needs an incident or ticket reference.

ATO evidence

For ATO, retain the default-branch ruleset export, required-review settings, CODEOWNERS routing, governance script output, validation logs, custom-property schema, a representative PR, and any bypass audit log. These support separation of duties, controlled configuration changes, least privilege, and auditability.

See also