Protection rules and permissions
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
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:
- Permission levels, precedence, and rule conflicts.
- Force push permissions across multiple matching rules.
- Code Owner approvals.
- Protection settings between groups and projects.
Push and merge permissions
Version history
- Branch push permission changed to require GitLab administrators to also have the allowed permission in GitLab 16.0.
When a branch is protected, the default behavior enforces these restrictions on the branch:
Action | Who can do it |
---|---|
Protect a branch | At least the Maintainer role. |
Push to the branch | Anyone with Allowed permission. (1) |
Force push to the branch | No one. |
Delete the branch | No one. (2) |
- Users with the Developer role can create a project in a group, but might not be allowed to initially push to the default branch.
- No one can delete a protected branch using Git commands, however, users with at least Maintainer role can delete a protected branch from the UI or API.
When a branch matches multiple rules
When a branch matches multiple rules, the most permissive rule determines the level of protection for the branch. For example, consider these rules, which include wildcards:
Branch name pattern | Allowed to merge | Allowed to push and merge |
---|---|---|
v1.x |
Maintainer | Maintainer |
v1.* |
Maintainer + Developer | Maintainer |
v* |
No one | No one |
A branch named v1.x
is a case-sensitive match for 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:
-
Allowed to merge: Of the three settings,
Maintainer + Developer
is most permissive, and controls branch behavior as a result. Even though the branch also matchedv1.x
andv*
(which each have stricter permissions), users with the Developer role can merge into the branch. -
Allowed to push and merge: Of the three settings,
Maintainer
is the most permissive, and controls branch behavior as a result. Even though branches matchingv*
are set toNo one
, branches that also matchv1.x
orv1.*
receive the more permissiveMaintainer
permission.
To be certain that a rule controls the behavior of a branch, all other patterns that match must apply less or equally permissive rules.
If you want to ensure that No one
is allowed to push to branch v1.x
, every pattern
that matches v1.x
must set Allowed to push and merge
to No one
, like this:
Branch name pattern | Allowed to merge | Allowed to push and merge |
---|---|---|
v1.x |
Maintainer | No one |
v1.* |
Maintainer + Developer | No one |
v* |
No one | No one |
Force push permissions
When a branch matches multiple rules, the most permissive rule determines whether force push is allowed. 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:
-
Allow force push: Of the three settings,
Yes
is most permissive, and controls branch behavior as a result. Even though the branch also matchedv1.x
andv*
(which each have stricter permissions), any user that can push to this branch can also force push.
Code owner approvals
- Tier: Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
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 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.
Unlike push, merge, and force push permissions (which use the most permissive rule), code owner approval uses the most restrictive rule. If any rule requires code owner approval, then all merge requests to matching branches require approval.
Rules across groups and projects
Branch protection rules can be set in both groups and projects:
- Group rules apply to all projects in a group and cannot be overridden.
- Project rules apply only to that specific project.
When both group and project rules exist that match a branch:
- Group rules always take precedence over project rules.
- If multiple group rules match a branch, the most permissive rule applies.
- If no group rules match but multiple project rules match, the most permissive project rule applies.
For example, if a group owner set up a rule requiring Code Owner approval for the main
branch,
project maintainers cannot disable this requirement in the project.
Examples
The following examples illustrate how protection rules work in practice.
Merge permission
Assume you have these rules set up:
Branch name pattern | Allowed to merge |
---|---|
development |
Developers + Maintainers |
dev* |
Maintainers only |
* |
No one |
With these rules:
- For a branch named
development
: Developers and Maintainers can merge (fromdevelopment
rule). - For a branch named
dev-feature
: Maintainers can merge (fromdev*
rule). - For a branch named
feature
: No one can merge (from*
rule).
Push permission
Assume you have these rules set up:
Branch name pattern | Allowed to push and merge |
---|---|
production |
No one |
prod* |
Maintainers only |
* |
Developers + Maintainers |
With these rules:
- For a branch named
production
: No one can push (fromproduction
rule). - For a branch named
prod-release
: Maintainers can push (fromprod*
rule). - For a branch named
feature
: Developers and Maintainers can push (from*
rule).
Direct push permission
Assume you have these rules set up:
Branch name pattern | Allowed to merge | Allowed to push and merge |
---|---|---|
main |
Everyone with access | No one |
m* |
Maintainers only | Maintainers only |
With these rules:
- For a branch named
main
:- Everyone with access can create merge requests.
- No one can push directly (must use merge requests).
- For a branch named
maintenance
:- Only Maintainers can create merge requests.
- Only Maintainers can push directly.
Code owner approval
Assume you have these rules set up:
Branch name pattern | Code owner approval required | Allowed to push and merge |
---|---|---|
release-* |
Yes | Maintainers only |
rel* |
No | Maintainers only |
With these rules:
- For a branch named
release-1.0
:- Code owner approval is required for merge requests.
- Only Maintainers can push directly.
- For a branch named
relations-feature
:- Code owner approval is not required.
- Only Maintainers can push directly.