GitHub Branch Protection Rules and Rulesets: Protect main Step by Step

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.

Advertisement

๐Ÿ“– 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 main only 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:

SettingWhat it enforces
Require a pull request before mergingNo 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 pushedRe-review after changes
Require review from Code OwnersOwners of changed files must approve (CODEOWNERS)
Require status checks to passSelected CI jobs must succeed
Require branches to be up to date before mergingPR must include the latest main (tests run on the combined code)
Require conversation resolutionAll review comments resolved
Require signed commitsCommits must be verified (GPG, SSH or S/MIME)
Require linear historyNo merge commits (squash or rebase only)
Lock branchRead-only branch (e.g. old releases)
Do not allow bypassing the above settingsApplies rules to administrators too
Allow force pushes / Allow deletionsLeave 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

RuleSetting
Target branchesDefault 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 listEmpty (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

BranchSuggested protection
mainPR 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 branchesUsually unprotected

Match protections to your branching strategy.


๐Ÿ“ Assignment

  1. In your public git-practice repository, create a ruleset (or classic rule) for main: PR required, 1 approval, no force pushes, no deletions.
  2. Try git push origin main directly and read the rejection message.
  3. 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.
  4. Make the job fail on purpose and observe that merging is blocked.
  5. 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

๐ŸŽฌ 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”

Leave a Comment