A branch protection rule (Settings, Branches) guards the branches matching one pattern, such as release/*, by requiring pull requests, approvals, status checks, signed commits or a linear history. Only one rule applies to a branch, and administrators are exempt unless the rule includes them. Sam commits a CODEOWNERS file (CODEOWNERS) on main, protects main through the REST API, and pushes:
cat > classic.json <<'EOF'
{ "required_status_checks": null, "enforce_admins": true, "restrictions": null,
"required_pull_request_reviews": { "required_approving_review_count": 0 } }
EOF
gh api -X PUT repos/{owner}/{repo}/branches/main/protection --input classic.json \
--jq '{admins: .enforce_admins.enabled,
reviews: .required_pull_request_reviews.required_approving_review_count}'
git push origin main{"admins":true,"reviews":0}
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote:
remote: - Changes must be made through a pull request.
To https://github.com/binarybehemoth/booknest.git
! [remote rejected] main -> main (protected branch hook declined)
...enforce_admins applied the rule to Sam, the owner, too. The endpoint takes an exact branch name; patterns need the web form or GraphQL. Classic rules still work, but GitHub 29 now recommends rulesets, so Sam deletes the rule with gh 29 api -X DELETE repos/{owner}/{repo}/branches/main/protection and rebuilds it as a ruleset.