Protected Branches
Branch protection rules stop risky changes from reaching important branches.
A protected branch has rules that must be satisfied before anyone can change it. Teams protect main to keep it stable.
Common rules
- Require a pull request before merging.
- Require one or more approvals.
- Require status checks (like CI) to pass.
- Block force pushes and branch deletion.
Configure these under Settings → Branches → Branch protection rules (or the newer Rulesets).
Example
# With rules enabled, direct pushes to main are rejected:
git push origin main
# ! [remote rejected] main -> main (protected branch hook declined)
# The correct flow is a pull request instead
git switch -c fix/typo
git push -u origin fix/typoWhen to use it
- A team protects main to require two approvals on every pull request, preventing anyone from pushing directly and breaking the build.
- A company requires status checks (CI tests) to pass before a PR can merge to main, ensuring broken code never reaches production.
- A GitHub administrator uses rulesets to enforce the same branch protection policy across every repo in the organisation.
More examples
Enable branch protection via CLI
Applies a branch protection rule via the REST API: requires the CI check to pass and one PR review before merging.
gh api repos/{owner}/{repo}/branches/main/protection \
--method PUT \
--input - << 'JSON'
{
"required_status_checks": { "strict": true, "contexts": ["ci/tests"] },
"enforce_admins": true,
"required_pull_request_reviews": { "required_approving_review_count": 1 },
"restrictions": null
}
JSONTest that direct push is blocked
Attempting to push directly to the protected branch returns an error, proving the protection rule is active.
git switch main
echo 'hotfix' >> README.md
git add README.md && git commit -m "test direct push"
git push origin main
# remote: error: GH006: Protected branch update failed.
# remote: Required status check "ci/tests" is expected.Create an organisation-wide ruleset
Creates a ruleset at the organisation level that applies to the main branch in every repository, replacing per-repo protection settings.
gh api orgs/{org}/rulesets \
--method POST \
-f name="require-pr-on-main" \
-f target="branch" \
-f enforcement="active" \
-f "conditions.ref_name.include[]"="refs/heads/main" \
-f "rules[0].type"="pull_request"
Discussion