How to Set Up Branch Protection Rules in GitHub
Branch protection rules are the guardrails that prevent a single bad merge from taking down production. They enforce code review requirements, mandate passing CI checks, and block force pushes to critical branches. Without them, even disciplined teams eventually have an incident caused by a well-intentioned but unreviewed direct push to main.
The challenge is configuring protection rules that enforce quality without creating bottlenecks. Overly strict rules lead to developers finding workarounds; overly permissive rules provide a false sense of security. This guide walks through setting up rules that match your team's actual workflow and scale as your codebase grows.
Step-by-step guide
Navigate to branch protection settings
Go to your repository on GitHub, click Settings, then Branches in the left sidebar. Under 'Branch protection rules,' click 'Add rule.' In the 'Branch name pattern' field, enter 'main' (or 'master' if that is your default branch). You can also use wildcard patterns like 'release/*' to protect all release branches with the same rules.
- Open your repository Settings > Branches
- Click 'Add branch protection rule'
- Enter 'main' as the branch name pattern
Require pull request reviews
Check 'Require a pull request before merging' and set the required number of approving reviews. For most teams, 1 approval is sufficient for feature branches and 2 for release branches. Enable 'Dismiss stale pull request approvals when new commits are pushed' so that a new commit after approval requires re-review. This prevents the pattern where a developer gets approval, then adds a quick 'small fix' that bypasses review.
- Enable 'Require a pull request before merging'
- Set required approvals to 1 or 2
- Enable 'Dismiss stale approvals when new commits are pushed'
Require status checks to pass
Check 'Require status checks to pass before merging' and search for your CI workflow names. Add your test suite, linting, and build checks as required. Enable 'Require branches to be up to date before merging' to ensure CI runs against the latest main, not a stale branch. This catches integration issues where two PRs individually pass but conflict when combined.
- Enable 'Require status checks to pass before merging'
- Add your CI test, lint, and build checks as required
- Enable 'Require branches to be up to date before merging'
Block force pushes and branch deletion
Ensure 'Allow force pushes' is unchecked and 'Allow deletions' is unchecked. Force pushes to main can rewrite shared history and cause every developer to have to re-clone or manually fix their local state. Branch deletion protection prevents accidental removal of your primary branch. These settings should be non-negotiable on any branch that reaches production.
Configure conversation resolution requirements
Enable 'Require conversation resolution before merging' to ensure all review comments are addressed before a PR can be merged. This prevents the common antipattern where a reviewer leaves important feedback that gets buried in a thread and never addressed. Combined with required reviews, this ensures substantive review, not just rubber-stamp approvals.
Set up CODEOWNERS for critical paths
Create a CODEOWNERS file in the root of your repository that maps file paths to required reviewers. For example, assign your infrastructure team as required reviewers for Dockerfile and CI config changes, and your security team for authentication-related files. When paired with 'Require review from Code Owners,' this ensures domain experts review changes to the areas they own.
- Create a .github/CODEOWNERS file in your repository
- Map critical file paths to team or individual reviewers
- Enable 'Require review from Code Owners' in branch protection
Test and communicate the rules
Before enforcing rules on the whole team, test them yourself by creating a test PR. Verify that the required checks appear, that you cannot merge without approval, and that force push is blocked. Then communicate the new rules to your team with a brief explanation of why each rule exists. Document the rules in your repository's contributing guide so new team members understand the workflow.
Common mistakes
Exempting administrators from all rules
GitHub offers an 'Include administrators' option. Leaving it unchecked means admins can bypass every rule. This defeats the purpose since the people most likely to make urgent production pushes are exactly the ones who should have review. Enable this option and use the bypass list only for automated bot accounts like Dependabot.
Not requiring up-to-date branches
Without 'Require branches to be up to date,' two PRs that individually pass CI can be merged sequentially even if they conflict when combined. The second merge can break main with no failing check. Enable this setting and use merge queues for high-throughput repositories.
Setting too many required reviewers
Requiring 3 or more approvals on every PR creates a bottleneck that slows development and incentivizes rubber-stamp reviews. Start with 1 required reviewer and increase only for specific paths via CODEOWNERS. Quality of review matters more than quantity.
Forgetting to protect release branches
Teams often protect main but leave release branches unprotected. Use wildcard patterns like 'release/*' to apply rules to all release branches. An unprotected release branch is a direct path to pushing unreviewed code to production.
Tips
Use GitHub's merge queue feature on high-velocity repositories to automatically batch and test PRs against each other before merging, eliminating the 'require up to date' bottleneck.
Create a separate, stricter rule set for paths like '.github/workflows/' and 'infrastructure/' using CODEOWNERS, so routine code changes flow quickly while high-risk changes get extra scrutiny.
Set up a GitHub Actions workflow that posts a comment on PRs listing which protection rules are satisfied and which are pending, giving authors clear visibility into merge readiness.
Review your branch protection rules quarterly. As your team and CI pipeline evolve, rules that made sense six months ago may now be causing unnecessary friction or missing new risks.
How Vantage helps
When defining engineering workflows in your PRDs, Vantage integrates with your GitHub repositories to understand your existing branch structure and CI setup. This means generated tickets can reference the correct branch strategy, and requirements can specify code review expectations that match your actual protection rules.