Use this API to manage branch protections for your repositories.
GitLab Premium and GitLab Ultimate support more granular protections for pushing to branches. Administrators can grant permission to modify and push to protected branches only to deploy keys, instead of specific users.
Valid access levelsThe ProtectedRefAccess.allowed_access_levels
method defines the following access levels:
0
: No access30
: Developer role40
: Maintainer role60
: AdministratorHistory
Gets a list of protected branches from a project as they are defined in the UI. If a wildcard is set, it is returned instead of the exact name of the branches that match that wildcard.
GET /projects/:id/protected_branches
Attribute Type Required Description id
integer or string yes The ID or URL-encoded path of the project search
string no Name or part of the name of protected branches to be searched for
In the following example, the project ID is 5
.
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches"
The following example response includes:
100
and 101
.push_access_levels
with IDs 1001
, 1002
, and 1003
.merge_access_levels
with IDs 2001
and 2002
.[
{
"id": 100,
"name": "main",
"push_access_levels": [
{
"id": 1001,
"access_level": 40,
"access_level_description": "Maintainers"
},
{
"id": 1002,
"access_level": 40,
"access_level_description": "Deploy key",
"deploy_key_id": 1
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
},
{
"id": 101,
"name": "release/*",
"push_access_levels": [
{
"id": 1003,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"merge_access_levels": [
{
"id": 2002,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
},
...
]
Users on GitLab Premium or Ultimate also see the user_id
, group_id
and inherited
parameters. If the inherited
parameter exists, means the setting was inherited from the project’s group.
The following example response includes:
100
.push_access_levels
with IDs 1001
and 1002
.merge_access_levels
with ID 2001
.[
{
"id": 101,
"name": "main",
"push_access_levels": [
{
"id": 1001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
},
{
"id": 1002,
"access_level": 40,
"access_level_description": "Deploy key",
"deploy_key_id": 1,
"user_id": null,
"group_id": null
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": null,
"user_id": null,
"group_id": 1234,
"access_level_description": "Example Merge Group"
}
],
"allow_force_push":false,
"code_owner_approval_required": false,
"inherited": true
},
...
]
Get a single protected branch or wildcard protected branch
Gets a single protected branch or wildcard protected branch.
GET /projects/:id/protected_branches/:name
In the following example, the project ID is 5
and branch name is main
:
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches/main"
Example response:
{
"id": 101,
"name": "main",
"push_access_levels": [
{
"id": 1001,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Users on GitLab Premium or Ultimate also see the user_id
and group_id
parameters:
Example response:
{
"id": 101,
"name": "main",
"push_access_levels": [
{
"id": 1001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": null,
"user_id": null,
"group_id": 1234,
"access_level_description": "Example Merge Group"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Protect repository branches
History
deploy_key_id
configuration introduced in GitLab 17.5.Protects a single repository branch or several project repository branches using a wildcard protected branch.
POST /projects/:id/protected_branches
Attribute Type Required Description id
integer or string yes The ID or URL-encoded path of the project. name
string yes The name of the branch or wildcard. allow_force_push
boolean no When enabled, members who can push to this branch can also force push. (default: false
) allowed_to_merge
array no Array of merge access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, or {access_level: integer}
. Premium and Ultimate only. allowed_to_push
array no Array of push access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, {deploy_key_id: integer}
, or {access_level: integer}
. Premium and Ultimate only. allowed_to_unprotect
array no Array of unprotect access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, or {access_level: integer}
. The access level No access
is not available for this field. Premium and Ultimate only. code_owner_approval_required
boolean no Prevent pushes to this branch if it matches an item in the CODEOWNERS
file. (defaults: false) Premium and Ultimate only. merge_access_level
integer no Access levels allowed to merge. (defaults: 40
, Maintainer role). push_access_level
integer no Access levels allowed to push. (defaults: 40
, Maintainer role) unprotect_access_level
integer no Access levels allowed to unprotect. (defaults: 40
, Maintainer role)
In the following example, the project ID is 5
and branch name is *-stable
.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30&unprotect_access_level=40"
The example response includes:
101
.push_access_levels
with ID 1001
.merge_access_levels
with ID 2001
.unprotect_access_levels
with ID 3001
.{
"id": 101,
"name": "*-stable",
"push_access_levels": [
{
"id": 1001,
"access_level": 30,
"access_level_description": "Developers + Maintainers"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 30,
"access_level_description": "Developers + Maintainers"
}
],
"unprotect_access_levels": [
{
"id": 3001,
"access_level": 40,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Users on GitLab Premium or Ultimate also see the user_id
and group_id
parameters:
The following example response includes:
101
.push_access_levels
with ID 1001
.merge_access_levels
with ID 2001
.unprotect_access_levels
with ID 3001
.{
"id": 1,
"name": "*-stable",
"push_access_levels": [
{
"id": 1001,
"access_level": 30,
"user_id": null,
"group_id": null,
"access_level_description": "Developers + Maintainers"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 30,
"user_id": null,
"group_id": null,
"access_level_description": "Developers + Maintainers"
}
],
"unprotect_access_levels": [
{
"id": 3001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Example with user push access and group merge access
Elements in the allowed_to_push
/ allowed_to_merge
/ allowed_to_unprotect
array should take the form {user_id: integer}
, {group_id: integer}
, or {access_level: integer}
. Each user must have access to the project and each group must have this project shared. These access levels allow more granular control over protected branch access. For more information, see configure group permissions.
The following example request creates a protected branch with user push access and group merge access. The user_id
is 2
and the group_id
is 3
.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&allowed_to_push%5B%5D%5Buser_id%5D=2&allowed_to_merge%5B%5D%5Bgroup_id%5D=3"
The following example response includes:
101
.push_access_levels
with ID 1001
.merge_access_levels
with ID 2001
.unprotect_access_levels
with ID 3001
.{
"id": 101,
"name": "*-stable",
"push_access_levels": [
{
"id": 1001,
"access_level": null,
"user_id": 2,
"group_id": null,
"access_level_description": "Administrator"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": null
"user_id": null,
"group_id": 3,
"access_level_description": "Example Merge Group"
}
],
"unprotect_access_levels": [
{
"id": 3001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Example with deploy key access
History
Elements in the allowed_to_push
array should take the form {user_id: integer}
, {group_id: integer}
, {deploy_key_id: integer}
, or {access_level: integer}
. The deploy key must be enabled for your project and it must have write access to your project repository. For other requirements, see Allow deploy keys to push to a protected branch.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&allowed_to_push[][deploy_key_id]=1"
The following example response includes:
101
.push_access_levels
with ID 1001
.merge_access_levels
with ID 2001
.unprotect_access_levels
with ID 3001
.{
"id": 101,
"name": "*-stable",
"push_access_levels": [
{
"id": 1001,
"access_level": null,
"user_id": null,
"group_id": null,
"deploy_key_id": 1,
"access_level_description": "Deploy"
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
}
],
"unprotect_access_levels": [
{
"id": 3001,
"access_level": 40,
"user_id": null,
"group_id": null,
"access_level_description": "Maintainers"
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Example with allow to push and allow to merge access
History
Example request:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"name": "main",
"allowed_to_push": [
{"access_level": 30}
],
"allowed_to_merge": [
{"access_level": 30},
{"access_level": 40}
]
}'
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches"
The following example response includes:
105
.push_access_levels
with ID 1001
.merge_access_levels
with IDs 2001
and 2002
.unprotect_access_levels
with ID 3001
.{
"id": 105,
"name": "main",
"push_access_levels": [
{
"id": 1001,
"access_level": 30,
"access_level_description": "Developers + Maintainers",
"user_id": null,
"group_id": null
}
],
"merge_access_levels": [
{
"id": 2001,
"access_level": 30,
"access_level_description": "Developers + Maintainers",
"user_id": null,
"group_id": null
},
{
"id": 2002,
"access_level": 40,
"access_level_description": "Maintainers",
"user_id": null,
"group_id": null
}
],
"unprotect_access_levels": [
{
"id": 3001,
"access_level": 40,
"access_level_description": "Maintainers",
"user_id": null,
"group_id": null
}
],
"allow_force_push":false,
"code_owner_approval_required": false
}
Examples with unprotect access levels
To create a protected branch where only a specific group can remove the protection:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"name": "production",
"allowed_to_unprotect": [
{"group_id": 789}
]
}' \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches"
To allow multiple types of users to unprotect a branch:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"name": "main",
"allowed_to_unprotect": [
{"user_id": 123},
{"group_id": 456},
{"access_level": 40}
]
}' \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches"
This configuration allows these users to unprotect the branch:
123
.456
.Unprotects the given protected branch or wildcard protected branch.
DELETE /projects/:id/protected_branches/:name
In the following example, the project ID is 5
and branch name is *-stable
.
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches/*-stable"
Update a protected branch
History
deploy_key_id
configuration introduced in GitLab 17.5.Updates a protected branch.
PATCH /projects/:id/protected_branches/:name
Attribute Type Required Description id
integer or string yes The ID or URL-encoded path of the project. name
string yes The name of the branch or wildcard. allow_force_push
boolean no When enabled, members who can push to this branch can also force push. allowed_to_merge
array no Array of merge access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, or {access_level: integer}
. Premium and Ultimate only. allowed_to_push
array no Array of push access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, {deploy_key_id: integer}
, or {access_level: integer}
. Premium and Ultimate only. allowed_to_unprotect
array no Array of unprotect access levels, with each described by a hash of the form {user_id: integer}
, {group_id: integer}
, {access_level: integer}
, or {id: integer, _destroy: true}
to destroy an existing access level. The access level No access
is not available for this field. Premium and Ultimate only. code_owner_approval_required
boolean no Prevent pushes to this branch if it matches an item in the CODEOWNERS
file. Premium and Ultimate only.
In the following example, the project ID is 5
and branch name is feature-branch
.
curl --request PATCH \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches/feature-branch?allow_force_push=true&code_owner_approval_required=true"
Elements in the allowed_to_push
, allowed_to_merge
and allowed_to_unprotect
arrays should be one of user_id
, group_id
or access_level
, and take the form {user_id: integer}
, {group_id: integer}
or {access_level: integer}
.
allowed_to_push
includes an extra element, deploy_key_id
, that takes the form {deploy_key_id: integer}
.
To update:
user_id
: Ensure the updated user has access to the project. You must also pass the id
of the access_level
in the respective hash.group_id
: Ensure the updated group has this project shared. You must also pass the id
of the access_level
in the respective hash.deploy_key_id
: Ensure the deploy key is enabled for your project and it must have write access to your project repository.To delete:
_destroy
set to true
. See the following examples.push_access_level
record
curl --header 'Content-Type: application/json' --request PATCH \
--data '{"allowed_to_push": [{"access_level": 40}]}' \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/22034114/protected_branches/main"
Example response:
{
"name": "main",
"push_access_levels": [
{
"id": 12,
"access_level": 40,
"access_level_description": "Maintainers",
"user_id": null,
"group_id": null
}
]
}
Example: update a push_access_level
record
curl --header 'Content-Type: application/json' --request PATCH \
--data '{"allowed_to_push": [{"id": 12, "access_level": 0}]}' \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/22034114/protected_branches/main"
Example response:
{
"name": "main",
"push_access_levels": [
{
"id": 12,
"access_level": 0,
"access_level_description": "No One",
"user_id": null,
"group_id": null
}
]
}
Example: delete a push_access_level
record
curl --header 'Content-Type: application/json' --request PATCH \
--data '{"allowed_to_push": [{"id": 12, "_destroy": true}]}' \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/22034114/protected_branches/main"
Example response:
{
"name": "main",
"push_access_levels": []
}
Example: update an unprotect_access_level
record
To modify who can unprotect an existing protected branch:
curl --request PATCH \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"allowed_to_unprotect": [
{"id": 17486, "user_id": 3791}
]
}' \
--url "https://gitlab.example.com/api/v4/projects/5/protected_branches/main"
When updating unprotect permissions:
allowed_to_unprotect
configurationid
of the existing access level record.user_id
must be a project member.group_id
must have access to the project._destroy: true
to remove specific access levelsRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4