GitHub: Settings → Branches → Add rule. Enter branch name pattern (main, develop, release/*). Enable: Require PR review, Require status checks, Restrict push access. Save.
✦ Definition~90s read
What is Branch Protection Rules?
Branch protection rules enforce restrictions on Git branches. Common rules: require PR reviews, require CI to pass, prevent direct pushes, require signed commits, require up-to-date branches before merging.
★
Branch protection rules are the bouncers at the club door.
Plain-English First
Branch protection rules are the bouncers at the club door. Main is the VIP section — not everyone can enter, and those who do need to follow the dress code (PR reviews, passing CI). Without bouncers, anyone walks in, spills drinks (breaks the build), and the club descends into chaos. Protection rules automate the bouncer: no PR? No entry. CI failing? No entry. Wrong branch? No entry.
Branch protection rules are the most important Git configuration you'll set up. They prevent the most common and most damaging Git mistakes: direct pushes to main, un-reviewed code reaching production, and broken builds being merged. Without protection rules, a single developer error can take down production. With them, every change to main goes through an automated gate. This guide covers the essential protection rules, the incident where a 'hotfix' bypassed all review and broke production, and how to configure branch protection for your workflow.
Configuring Branch Protection on GitHub
GitHub branch protection rules are configured per repository. Go to Settings → Branches → Add rule.
Essential rules for main: - Require PR review before merging: Set to 1 or 2 reviewers. This prevents direct pushes. - Dismiss stale reviews: When new commits are pushed, existing approvals are dismissed, requiring re-review. - Require status checks: Select CI checks that must pass (lint, test, build, security scan). - Require branches to be up to date: The PR branch must be based on the latest main. Prevents conflicts. - Restrict who can push: Only allow specific users/teams or the CI bot. - Allow force pushes: NEVER enable this for main. Set to 'Everyone' or 'Specific actors' only for non-main branches.
Additional security rules: - Require signed commits: Only GPG-signed commits accepted on this branch. - Include administrators: Apply rules to admins too — nobody is above the process.
01_branch_protection.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Check current branch protection (via GitHubAPI)
gh api repos/:owner/:repo/branches/main/protection
# Create a branch protection rule (via gh cli)
# Note: gh doesn't have a direct 'protect' command, use API
gh api --method PUT repos/:owner/:repo/branches/main/protection \
--input - << 'EOF'
{
"required_status_checks": {
"strict": true,
"contexts": ["continuous-integration", "lint", "test"]
},
"required_pull_request_reviews": {
"required_approving_review_count": 1,
"dismiss_stale_reviews": true
},
"enforce_admins": true,
"restrictions": null
}
EOF
# Apply rule to multiple branches using pattern
echo "main" # or release/*, develop, etc.
# Remove protection rule
gh api --method DELETE repos/:owner/:repo/branches/main/protection
By default, GitHub admins can bypass branch protection. Always enable 'Include administrators' to apply rules to everyone. If an admin needs to bypass (genuine emergency), they can temporarily disable the rule — but this creates an audit trail.
Production Insight
Use branch name patterns to apply rules broadly: main for production, develop for integration, release/ for release branches, feature/ for feature branches (with relaxed rules). For emergency hotfixes, create a hotfix/* pattern with reduced requirements (1 reviewer instead of 2, fewer CI checks) — this provides a documented escape hatch without allowing completely unguarded pushes.
Key Takeaway
Branch protection rules prevent direct pushes, enforce PR reviews, require passing CI, and block unsigned commits. Configure on main, develop, and release branches. Include admins in protection. Create a documented hotfix branch for emergencies with relaxed rules.
● Production incidentPOST-MORTEMseverity: high
The 'Urgent' Hotfix That Bypassed All Gates and Broke Production
Symptom
A senior engineer pushed a 'critical hotfix' directly to main to 'save time.' The fix had a typo that broke the entire payments module. No code review caught it. No CI gate stopped it. Production was down for 2 hours.
Assumption
The engineer assumed urgency justified bypassing process. They didn't realize the hotfix had a bug that a 30-second review would have caught.
Root cause
1. A production bug was reported (minor UI glitch). 2. The engineer marked it as 'critical' and pushed directly to main without a PR. 3. The 'fix' had a JavaScript syntax error (missing closing parenthesis). 4. No CI check ran (the engineer pushed with --no-verify). 5. The broken commit was deployed immediately (the CI/CD pipeline auto-deployed main). 6. The payments module crashed for all users. 7. Rolling back took 2 hours because the engineer who pushed was on a call and unreachable.
Fix
1. Immediately: reverted the commit on main via GitHub UI (revert button). 2. Disabled the auto-deploy pipeline temporarily. 3. Fixed the hotfix properly: created a branch, opened a PR with review, passed CI. 4. Configured branch protection on main: require PR review, require CI to pass, restrict push access to main to the CI bot only. 5. Added an emergency hotfix process: a 'hotfix' branch with relaxed rules but at least one review required.
Key lesson
Branch protection rules are the most important Git security measure.
Require PR reviews AND CI checks on main.
Restrict direct push access to CI bots only.
Create a documented hotfix process for genuine emergencies.
Production debug guideUse this when production is on fire3 entries
Symptom · 01
Need to prevent direct pushes to main
→
Fix
Enable 'Require PR review' and 'Restrict who can push to matching branches'
Symptom · 02
Need to ensure CI passes before merge
→
Fix
Enable 'Require status checks to pass before merging'
Symptom · 03
Need to require signed commits
→
Fix
Enable 'Require signed commits' — only GPG-signed commits are accepted
Key takeaways
1
Protection rules prevent the most common and damaging Git mistakes