doc/user/project/repository/branches/protection_rules.md
{{< details >}}
{{< /details >}}
Protection rules control access to branches and determine what happens when multiple rules apply to the same branch. They help you implement the right security measures for your repository branches. These rules cover:
When a branch matches multiple protection rules, these behaviors apply:
main do not override wildcard patterns like m*.{{< history >}}
{{< /history >}}
When a branch is protected, the default behavior enforces these restrictions:
| Action | Who can do it |
|---|---|
| Protect a branch | Users with the Maintainer or Owner role. |
| Push to the branch | Anyone with Allowed permission. (1) |
| Force push to the branch | No one. |
| Delete the branch | No one. (2) |
When you configure these permissions, selecting a role grants access to users with that role and all higher roles. For example:
This behavior ensures that users with higher privileges retain access available to users with lower privileges.
Force push permissions follow the same most permissive rule applies logic. For example, consider these rules, which include wildcards:
| Branch name pattern | Allow force push |
|---|---|
v1.x | Yes |
v1.* | No |
v* | No |
A branch named v1.x matches all three branch name patterns: v1.x, v1.*, and v*.
As the most permissive option determines the behavior, the resulting permissions for branch v1.x are:
Yes is most permissive,
and controls branch behavior as a result. Even though the branch also matched v1.x and v*
(which each have stricter permissions), any user that can push to this branch can also force push.{{< details >}}
{{< /details >}}
Unlike push and merge permissions, and force push permissions, code owner approval uses the most restrictive rule. If a branch is protected by multiple rules, code owner approval is required if any of the applicable rules have Required approval from code owners enabled. For more information, see require code owner approval.
For example, consider these rules:
| Branch name pattern | Code owner approval required |
|---|---|
v1.x | Yes |
v1.* | No |
v* | No |
A branch named v1.x matches all three branch name patterns: v1.x, v1.*, and v*.
Because at least one rule (v1.x) requires code owner approval, all merge requests to this branch
require approval by a Code Owner before they can be merged.
Branch protection rules can be set in both groups and projects:
When both group and project rules match a branch, GitLab evaluates all matching rules together:
You cannot edit or remove group rules from project settings, but you can add project rules for the same branch. The combined evaluation can result in more permissive behavior than the group rule alone.
For example:
main disallows force push.main that allows force push.main branch.The following examples demonstrate how different rules can affect branch protection.
An example of how an exact branch name does not override a more permissive wildcard pattern.
| Branch pattern | Allowed to merge |
|---|---|
release-v1.0 | No one |
release* | Maintainer |
* | Developer + Maintainer |
release-v1.0 matches all three patterns. The most permissive rule applies:
* rule).An example of how multiple branch rules apply to different branch names.
| Branch pattern | Allowed to merge | Allowed to push and merge |
|---|---|---|
main | Maintainer | No one |
m* | Developer + Maintainer | Developer + Maintainer |
r* | No one | No one |
main matches two patterns (main and m*). The most permissive rule applies:
m* rule).m* rule).release-v1.0 matches one pattern:
r* rule).r* rule).Code owner approval works differently from other branch protection settings. When multiple rules match, the most restrictive rule applies instead of the most permissive.
| Branch pattern | Code owner approval required |
|---|---|
production | Yes |
prod* | No |
p* | Yes |
production matches all three patterns. The most restrictive rule applies:
production and p* rules).product-v1.0 matches two patterns (prod* and p*). The most restrictive rule applies:
p* rule).To ensure strict protection that cannot be overridden by more permissive patterns, configure all matching patterns with the same restrictive settings.
| Branch pattern | Allowed to merge | Allowed to push and merge |
|---|---|---|
production | Maintainer | No one |
prod* | Maintainer | No one |
p* | Maintainer | No one |
* | Maintainer | No one |
Now branch production has restrictive push permissions because all matching rules specify
No one can push.