Overview
Branch protection rules enforce the contract that main stays green. Without them, a single direct push or a merged PR with failing checks can take down the deploy. This page covers the rules worth enabling, what each one does, and the bypass scenarios you must close. Read github for the broader branching strategy and github-actions for the CI workflows that protection rules evaluate.
Require a pull request before merging
Enable “Require a pull request before merging” on every protected branch. This setting makes direct pushes to main impossible for all actors the rule covers.
Under this setting, choose “Required approvals: 1” for solo or small teams. For larger teams, raise the count to match the review burden you can realistically sustain. More required reviewers sounds safer but slows merges; a single required reviewer who reads diffs carefully is more effective than three who rubber-stamp.
Pair with “Dismiss stale pull request approvals when new commits are pushed” so an approval given before a force-push to the branch is automatically invalidated.
Require status checks to pass before merging
Every PR must pass the CI checks you name before it can merge. Configure this in Settings - Branches - Branch protection - “Require status checks to pass before merging.”
Add the check names by their exact job name from github-actions. Mark the critical ones as required; mark informational checks (coverage reports, bundle-size deltas) as optional. A required check that is flaky blocks every PR; keep the required set small and reliable.
Enable “Require branches to be up to date before merging” so a PR based on a stale main cannot merge, even if its own checks passed. This closes the class of bugs where two PRs both pass CI independently but fail together on main.
Enforce linear history on main
Enable “Require linear history.” This setting rejects merge commits on the protected branch, forcing all merges to use squash or rebase. The result is a main that reads as a single line in git log --oneline, which simplifies bisect, rollback, and changelog generation.
Linear history pairs with squash merge as the default merge strategy in github-pr-workflow. If you enable “Require linear history” without disabling merge commits in repo settings, contributors will see confusing errors at merge time.
Restrict who can push to matching branches
Enable “Restrict pushes that create matching branches” and “Block force pushes” together. Force pushes rewrite history that other people may have already pulled; they silently break local clones and CI runs mid-flight.
For repositories with automation that legitimately needs to push to main (deploy bots, automated changelog commits), grant the bot account a bypass role rather than leaving force pushes open. Bypass roles are auditable; open force-push permissions are not.
Require signed commits for high-trust repositories
Enable “Require signed commits” on repositories where code identity matters: internal tooling, packages published to a registry, and repos where supply-chain integrity is a concern. Signed commits verify that the author controls the key associated with the GPG signature, not just the GitHub account.
For most content repositories (including this one), signed commits add friction without meaningful security gain. Require them where the cost of a compromised commit is high.
Understand bypass actors and close unintended gaps
Bypass actors are identities that can merge or push without satisfying the protection rules. GitHub allows two bypass types: people/teams and apps. Common gaps:
- Repository admins bypass all rules by default in “classic” protection rules. Enable “Do not allow bypassing the above settings” to close this.
- GitHub Apps granted admin-level permissions (like some release bots) bypass protection. Audit installed apps in Settings - GitHub Apps.
- Organization owners bypass branch protection on repos in their org. Limit org owner accounts and require MFA for them.
Rules deployed via “Branch rulesets” (the newer API) have more granular bypass controls and apply to forks. Prefer rulesets over classic rules for new repositories.