Branch protection makes your team’s safe workflow mandatory: no direct pushes, required reviews and green CI before anything reaches main. In this lesson you will configure classic protection rules and modern rulesets, and connect required checks to GitHub Actions.
๐ What You’ll Learn: why protect branches, plan availability, every classic protection setting, rulesets and their advantages, a recommended ruleset for main, required status checks from GitHub Actions, rejected pushes, and protection by branch and tag.
๐ก๏ธ Why Protect Branches?
Without protection, anyone with write access can push directly to main, force-push over history or delete the branch. Branch protection makes the safe workflow mandatory:
- Changes reach
mainonly through pull requests. - Pull requests need approvals from reviewers (code review).
- CI checks (tests, lint, build) must pass before merging.
- Force pushes and deletions are blocked.
๐ Note: Branch protection and rulesets are available for public repositories on all plans. For private repositories, they require GitHub Pro, Team or Enterprise.
GitHub offers two systems: classic branch protection rules and newer rulesets. Both are covered below.
๐งฑ Classic Branch Protection Rules
Settings, Branches, Add branch protection rule (or Add classic branch protection rule). Enter the branch name pattern, e.g. main or release/*, and choose settings:
| Setting | What it enforces |
|---|---|
| Require a pull request before merging | No direct pushes; changes come through PRs |
| Require approvals (e.g. 1 or 2) | Minimum number of approving reviews |
| Dismiss stale approvals when new commits are pushed | Re-review after changes |
| Require review from Code Owners | Owners of changed files must approve (CODEOWNERS) |
| Require status checks to pass | Selected CI jobs must succeed |
| Require branches to be up to date before merging | PR must include the latest main (tests run on the combined code) |
| Require conversation resolution | All review comments resolved |
| Require signed commits | Commits must be verified (GPG, SSH or S/MIME) |
| Require linear history | No merge commits (squash or rebase only) |
| Lock branch | Read-only branch (e.g. old releases) |
| Do not allow bypassing the above settings | Applies rules to administrators too |
| Allow force pushes / Allow deletions | Leave off for main |
๐ Rulesets (Recommended for New Setups)
Settings, Rules, Rulesets, New ruleset, New branch ruleset. Rulesets offer the same protections plus:
- Several rulesets can apply at once and their rules are combined (the most restrictive wins).
- An enforcement status: Active or Disabled (and Evaluate mode on some plans, to test a ruleset without blocking anyone).
- A bypass list of roles, teams or apps allowed to bypass.
- Targeting by branch patterns, the default branch or all branches, plus tag rulesets to protect release tags (tags).
- Organisation-level rulesets on organisation plans, to apply one policy to many repositories.
- Anyone with read access can see which rules apply, so contributors understand why a push was rejected.
A sensible ruleset for main
| Rule | Setting |
|---|---|
| Target branches | Default branch |
| Restrict deletions | โ |
| Block force pushes | โ |
| Require a pull request before merging | โ 1 approval, dismiss stale approvals, require Code Owner review |
| Require status checks to pass | โ e.g. “playwright-tests”, “lint” |
| Require conversation resolution | โ |
| Bypass list | Empty (or a release bot) |
โ Required Status Checks with GitHub Actions
Status checks are the job names from your workflows. A job must have run at least once (for example on a PR) before GitHub lets you pick it in the rule.
# .github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
playwright-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
Select lint and playwright-tests as required checks. A PR with failing tests then shows Merging is blocked. See Playwright in GitHub Actions.
๐งช What Happens When Someone Breaks the Rules?
$ git push origin main
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: - Changes must be made through a pull request.
! [remote rejected] main -> main (push declined due to repository rule violations)
The fix is the normal workflow: push a branch and open a pull request.
๐ก Recommended Protection by Branch
| Branch | Suggested protection |
|---|---|
main | PR required, 1 to 2 approvals, required CI checks, no force push, no deletion |
develop (Git Flow) | PR required, required CI checks |
release/* | PR required, required checks, Code Owner review |
Release tags v* | Tag ruleset: restrict creation and deletion to maintainers |
| Feature branches | Usually unprotected |
Match protections to your branching strategy.
๐ Assignment
- In your public
git-practicerepository, create a ruleset (or classic rule) formain: PR required, 1 approval, no force pushes, no deletions. - Try
git push origin maindirectly and read the rejection message. - Add a simple GitHub Actions workflow with a job named
lint(e.g.echo ok), run it on a PR, and make it a required status check. - Make the job fail on purpose and observe that merging is blocked.
- Add a tag ruleset that protects tags matching
v*from deletion.
โ FAQ
๐ค What is branch protection in GitHub?
Rules that control how changes reach a branch, such as requiring pull requests, approvals and passing CI checks, and blocking force pushes and deletions.
๐ค What is the difference between branch protection rules and rulesets?
Both protect branches. Rulesets are newer: several can apply at once, they have enforcement statuses and bypass lists, can protect tags and can be defined at organisation level.
๐ค How do I require tests to pass before merging?
Add the CI job names as required status checks in a branch protection rule or ruleset; the jobs must have run at least once.
๐ค Why can’t I push to main?
The branch is protected and requires changes through a pull request. Push a feature branch and open a PR.
๐ค Is branch protection free?
For public repositories, yes. For private repositories it requires a paid plan such as GitHub Pro, Team or Enterprise.
๐ฏ Next Steps
- ๐ฅ CODEOWNERS, Issue and Pull Request Templates
- ๐ Secrets, Dependabot and Code Scanning
- ๐ Git and GitHub Tutorial: full course
๐ฌ Learn Git and GitHub step by step: watch the series on YouTube!
Subscribe to SqaToolsByDY • Practice on sqatools.in
2 thoughts on “GitHub Branch Protection Rules and Rulesets: Protect main Step by Step”