The default branch takes changes only through a change request that passed CI, and rejects force pushes
Branch protection is the only rule here that a repository setting enforces rather than a file. Without it, every other rule in this document can be bypassed by one push. Every control this rule names binds a repository of any size, including one with a single maintainer, because none of them needs a second person to function.
Observable check
the default branch is protected, a pull request or merge request is the only path onto it, at least one CI status check must pass before merge, and force pushes and deletion are blocked. On GitHub the settings live in either of two places, so read both: gh api repos/{owner}/{repo}/rulesets for a ruleset, and gh api repos/{owner}/{repo}/branches/{branch}/protection for a classic rule, which answers 404 Branch not protected when a ruleset is what guards the branch. On GitLab, GET /projects/:id/protected_branches/:name.
Where this comes from
Last read against these sources on 2026-07-28.
Scorecard Branch-Protection covers force-push prevention and status checks, and names repository rules alongside classic protection. Its review requirement is R-SEC-12 rather than this rule. The GitHub and GitLab API endpoints the check reads have no source named.