GitHub Rulesets vs Branch Protection Rules: Which to Use
TL;DR · the short version
GitHub rulesets and classic branch protection rules can both protect a branch, and they work alongside each other: all applicable rules are enforced, and where two rules conflict the most restrictive one applies (GitHub Docs). The differences that matter for security are that only one branch protection rule applies to a branch while several rulesets can stack, rulesets can be switched between Active and Disabled without deleting them, rulesets can also target tags, anyone with read access can view a repository's active rulesets, and organisation-level rulesets that span many repositories are available on the GitHub Enterprise plan. The setting that decides whether either one is real is the bypass list: any role, team or app on it can step around the rules. Use rulesets for new work, keep the bypass list short and named, and check every required status check by name.
GitHub rulesets and branch protection rules do the same job in different ways, and you can run both. GitHub Docs say they "work alongside each other, and all applicable rules are enforced." Use rulesets for anything new, because several can stack on one branch, they can cover tags, and they can be switched off without being deleted. Whichever you use, the setting that decides whether the rules are real is who is allowed to bypass them.
Rulesets vs branch protection rules at a glance
| Question | Branch protection rule | Ruleset |
|---|---|---|
| How many apply to one branch? | One | Several; they have no priority and are combined |
| Two rules disagree | n/a (one rule) | The most restrictive version applies |
| Turn it off without deleting | No | Yes: set enforcement to Disabled |
| Can target tags | Not covered in GitHub's rulesets page | Yes (restrict creation, deletion, renames) |
| Who can see it | People with repository admin access | Anyone with read access can view active rulesets |
| Bypass | Admin setting | Explicit bypass list of roles, teams or GitHub Apps |
| Spans many repositories | No | Organisation rulesets, on the GitHub Enterprise plan |
Source: GitHub Docs, "About rulesets". Plan limits change, so check the current docs for your plan.
Why the bypass list matters more than the rule type
A review requirement that an administrator can skip is a suggestion. The October 2026 LiteLLM compromise, as publicly reported, was carried out with a credential that could step around protections, not by defeating them; our write-up is in LiteLLM supply-chain attack: what to do. Practical rules:
- Keep the bypass list empty, or limited to a named break-glass team that is alerted on use.
- Do not put "repository admin" on it as a convenience. A stolen admin token then inherits the bypass.
- Remember rulesets are readable. Anyone with read access can see which rules are Active, so the rules are not secret; the controls have to hold up when known.
- Prefer organisation-level rulesets where your plan allows, so one repository admin cannot loosen the rule for their own repo.
How to require status checks to pass
- In the repository, open Settings, then Rules, then Rulesets.
- Choose New ruleset then New branch ruleset (or edit an existing one).
- Under Target branches, add a target such as the default branch.
- Tick Require status checks to pass and add each check by name. Run the workflow once first so the check name appears.
- Set enforcement to Active, save, and open a test pull request to confirm it blocks the merge.
Two common mistakes: adding a check name that your workflow no longer reports (the merge then waits forever), and requiring a check that a path filter skips on some pull requests.
Fix: "This ruleset does not target any resources and will not be applied"
This message means the ruleset's target list is empty. It is saved but enforces nothing. Open the ruleset, add a target under Target branches (include the default branch, all branches, or a pattern such as release/*), and save. Then test with a pull request. An Active ruleset with no target is the most common reason a "protected" branch accepts a direct push.
A migration path from branch protection rules
- List the existing branch protection rules and what each enforces.
- Recreate them as a ruleset, set to Disabled first, so nothing changes yet.
- Switch to Active and test pull requests, direct pushes and force pushes.
- Remove the duplicate branch protection rule once the ruleset behaves as expected. Because the two stack, leaving both is safe but confusing.
- Review the bypass list last, and write down who is on it and why.
What security leaders should do this week
- Ask each team lead whether the default and release branches have required reviews, required status checks, blocked force pushes and an empty or tiny bypass list.
- Run the GitHub Branch Protection Checklist on your most important repository and fix the highest-severity gap first.
- Check the build side too: protected branches mean little if the release can be published with a stolen token. See the GitHub Release Integrity Checklist and the npm trusted publishing guide.
- Review who holds organisation-owner and repository-admin roles with the GitHub Token Scope Analyzer.
- More tools and guides are collected on the GitHub security hub.
FAQ
What is the difference between GitHub rulesets and branch protection rules?
Both enforce rules on branches and they work alongside each other. Only one branch protection rule applies to a branch, while multiple rulesets can apply at once; their rules combine and the most restrictive version wins. Rulesets can also target tags, be set to Active or Disabled, and (on the GitHub Enterprise plan) be created at organisation level.
Do rulesets replace branch protection rules?
No. GitHub says both can protect branches in the same repository and all applicable rules are enforced. When migrating, keep the old rule until the ruleset is Active and tested, then remove the duplicate.
How do I require status checks to pass in a ruleset?
Settings, Rules, Rulesets, edit or create a branch ruleset, tick Require status checks to pass and add each check by name. A check generally appears in the picker only after it has run in the repository, so run the workflow once first.
What does "This ruleset does not target any resources and will not be applied" mean?
The ruleset has no target branches or tags, so it enforces nothing even when Active. Add a target and save.
Who can bypass a GitHub ruleset?
Whoever is on its bypass list: a role such as repository administrator, specific teams or GitHub Apps. Keep the list empty or minimal, because anything on it can step around the rules and anyone with read access can see which rulesets are Active.
Sources
Educational guidance, not legal advice. Menu names and plan limits change; confirm against GitHub's current documentation.