Branch Protection Rules | Require PRs & CI Checks
Protect main, develop, and release branches: require PRs, approvals, passing CI. Prevent force pushes. Handle emergencies with bypass permissions and audit trail.
7 min read
Branch protection rules are your automated gatekeepers. They ensure code reviews happen, tests pass, and critical branches stay stable. Properly configured protection prevents costly mistakes and enforces team standards without manual policing.
Protection Options
| Protection | Purpose | Recommended |
|---|---|---|
| Require PR | No direct push | β Always |
| Require review | Code quality | β Always |
| Require CI | Tests pass | β Always |
| Up to date | No merge conflicts | β Usually |
| Block force push | Preserve history | β Always |
GitHub Configuration
Setting Up Protection
GITHUB BRANCH PROTECTION
ββββββββββββββββββββββββ
ACCESS:
βββββββββββββββββββββββββββββββββββββ
Settings β Branches β Add rule
βββ Branch name pattern: main
βββ Configure protections
REQUIRED PROTECTIONS:
βββββββββββββββββββββββββββββββββββββ
β Require a pull request before merging
βββ Required approvals: 1 (small team) or 2 (larger)
βββ Dismiss stale pull request approvals
β βββ Changes after approval need re-review
βββ Require review from Code Owners
β βββ Use CODEOWNERS file
βββ Require approval of most recent push
βββ Prevents sneaky commits after approval
β Require status checks to pass
βββ Require branches to be up to date
βββ Add checks:
β βββ ci/build
β βββ ci/test
β βββ ci/lint
β βββ security/scan
βββ All must pass before merge
β Require conversation resolution
βββ All PR comments must be resolved
β Require signed commits (optional)
βββ For high-security repos
PUSH RESTRICTIONS:
βββββββββββββββββββββββββββββββββββββ
β Restrict who can push to matching branches
βββ Select allowed teams/users
βββ Only for emergencies
βββ Usually: nobody (all via PR)
β Do not allow bypassing the above settings
βββ Even admins must follow rules
β Block force pushes
βββ Protect history
β Block deletions
βββ Can't delete protected branches
GitHub Rulesets
GITHUB RULESETS (NEWER)
βββββββββββββββββββββββ
ADVANTAGES OVER BRANCH RULES:
βββββββββββββββββββββββββββββββββββββ
βββ Apply at organization level
βββ Target multiple branches/repos
βββ More granular bypass permissions
βββ Tag rules included
βββ Better audit trail
βββ Recommended for enterprise
CREATING A RULESET:
βββββββββββββββββββββββββββββββββββββ
Repository β Settings β Rules β Rulesets
New ruleset:
βββ Name: "Production Protection"
βββ Enforcement: Active
βββ Target branches: main, release/*
βββ Configure rules
RULESET OPTIONS:
βββββββββββββββββββββββββββββββββββββ
Branch rules:
βββ Restrict creations
βββ Restrict updates
βββ Restrict deletions
βββ Require linear history
βββ Require deployments to succeed
βββ Require signed commits
βββ Require a pull request
βββ Require status checks
βββ Block force pushes
Bypass list:
βββ Repository admins
βββ Specific teams (e.g., Release Team)
βββ Deploy keys
βββ Emergency access defined
GitLab Configuration
Protected Branches
GITLAB PROTECTED BRANCHES
βββββββββββββββββββββββββ
ACCESS:
βββββββββββββββββββββββββββββββββββββ
Settings β Repository β Protected branches
CONFIGURATION:
βββββββββββββββββββββββββββββββββββββ
Branch: main
Allowed to merge:
βββ Maintainers (common)
βββ Developers + Maintainers
βββ No one (via MR only)
βββ Role-based control
Allowed to push:
βββ No one (recommended)
βββ Force CI/MR workflow
βββ All changes via MR
Allowed to force push:
βββ No (always)
βββ Protects history
Code owner approval:
βββ Required from CODEOWNERS
βββ Domain expertise enforced
MERGE REQUEST SETTINGS:
βββββββββββββββββββββββββββββββββββββ
Settings β Merge Requests
β Pipelines must succeed
β All threads must be resolved
β Skipped pipelines considered successful: No
β Merge method: Merge commit / Squash / Rebase
βββ Team preference
Status Checks
Requiring CI to Pass
STATUS CHECK CONFIGURATION
ββββββββββββββββββββββββββ
WHICH CHECKS TO REQUIRE:
βββββββββββββββββββββββββββββββββββββ
Essential:
βββ Build: Must compile/build
βββ Test: Unit tests pass
βββ Lint: Code standards met
βββ Non-negotiable gates
Recommended:
βββ Security scan
βββ Type checking
βββ Integration tests
βββ Coverage threshold
βββ Higher quality bar
Optional:
βββ Performance tests
βββ Preview deployment
βββ Documentation check
βββ Nice-to-have
SETTING UP CHECKS:
βββββββββββββββββββββββββββββββββββββ
1. Create workflow that reports status:
name: CI
on: pull_request
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- run: npm test
2. Add to required checks:
Settings β Branches β Edit rule
β Add "build" to required checks
HANDLING FLAKY TESTS:
βββββββββββββββββββββββββββββββββββββ
Options:
βββ Fix the flaky test (best)
βββ Retry logic in CI
βββ Remove from required (temporary)
βββ Don't let flaky block team
Emergency Bypass
Handling Urgent Fixes
EMERGENCY PROCEDURES
ββββββββββββββββββββ
BYPASS OPTIONS:
βββββββββββββββββββββββββββββββββββββ
Option 1: Bypass list
βββ Specific people can bypass
βββ Senior engineers / leads
βββ Emergency-only usage
βββ Audited in git history
βββ Define in ruleset
Option 2: Hotfix branch rules
βββ hotfix/* has lighter protection
βββ Maybe 1 reviewer vs 2
βββ Same CI requirements
βββ Faster path for urgent
βββ Separate protection rule
Option 3: Temporary disable
βββ Admin disables rule
βββ Push fix
βββ Re-enable immediately
βββ Document in incident log
βββ Last resort
βββ Has audit trail
EMERGENCY PROCESS:
βββββββββββββββββββββββββββββββββββββ
1. Create hotfix/* branch
2. Make minimal fix
3. Fast review (1 person)
4. CI must pass (abbreviated)
5. Merge to main
6. Cherry-pick to release if needed
7. Full post-mortem review
8. Log in incident record
BALANCE:
βββββββββββββββββββββββββββββββββββββ
βββ Protection is important
βββ Emergencies happen
βββ Define process ahead of time
βββ Don't make bypasses common
βββ Review after every bypass
βββ Continuous improvement
Code Owners
Domain-Based Review
CODEOWNERS FILE
βββββββββββββββ
PURPOSE:
βββββββββββββββββββββββββββββββββββββ
βββ Automatic review assignment
βββ Ensure right experts review
βββ Ownership of code areas
βββ Required approval for changes
βββ Domain expertise enforcement
FILE LOCATION:
βββββββββββββββββββββββββββββββββββββ
.github/CODEOWNERS
# or
docs/CODEOWNERS
# or
CODEOWNERS (root)
SYNTAX:
βββββββββββββββββββββββββββββββββββββ
# Default owners for everything
* @team-lead @senior-dev
# Frontend ownership
/src/components/ @frontend-team
*.tsx @frontend-team
*.css @frontend-team
# Backend ownership
/src/api/ @backend-team
/src/services/ @backend-team
# Infrastructure
/terraform/ @platform-team
/docker/ @platform-team
*.yml @devops-team
# Security sensitive
/src/auth/ @security-team @team-lead
/src/payments/ @security-team @backend-team
RESULT:
βββββββββββββββββββββββββββββββββββββ
βββ PR touching /src/auth/ β security-team auto-added
βββ Must approve for merge
βββ Domain experts involved
βββ No changes slip through
βββ Automatic assignment
GitScrum Integration
Protection Visibility
GITSCRUM WITH BRANCH PROTECTION
βββββββββββββββββββββββββββββββ
PR STATUS VISIBILITY:
βββββββββββββββββββββββββββββββββββββ
On task:
βββ PR status shown
βββ Checks passing/failing
βββ Review status
βββ Merge readiness
βββ At-a-glance health
WORKFLOW AWARENESS:
βββββββββββββββββββββββββββββββββββββ
βββ Task moves "In Review" β PR opened
βββ Task sees PR checks status
βββ Blocked if checks fail
βββ Unblocked when ready to merge
βββ Task status reflects reality
Best Practices
For Branch Protection
Anti-Patterns
BRANCH PROTECTION MISTAKES:
β No protection on main
β Admins bypass routinely
β Optional CI checks
β No required reviews
β Too many bypasses
β Force push allowed
β No CODEOWNERS for critical code
β Emergency process undefined