GitLab Protected Branches
A protected branch is a branch with extra rules about who can push, merge, or delete. The main branch usually holds working code, so teams lock it. Changes arrive through merge requests that pass review and pipelines.
Think of a bank vault. Tellers handle daily cash at the counter, and only authorized staff open the vault. Protection rules decide who holds the vault key.
What Protection Prevents
UNPROTECTED main PROTECTED main ─────────────────── ─────────────────── Any developer pushes directly Direct pushes blocked Force push rewrites history Force push blocked Anyone deletes the branch Deletion blocked Broken code reaches main fast Changes arrive by merge request
Default Protection
GitLab protects the default branch of a new project. The default rule allows Maintainers to merge and blocks direct pushes from lower roles. Administrators of self-managed servers adjust this default for the whole instance.
Check Protection Settings
- Open your project.
- Select Settings → Repository.
- Expand Protected branches.
The table lists each protected branch with its permissions.
Permission Options
| Setting | Choices | Meaning |
|---|---|---|
| Allowed to merge | Maintainers, Developers and Maintainers, No one | Who clicks Merge on a merge request |
| Allowed to push and merge | Maintainers, Developers and Maintainers, No one | Who pushes straight to the branch |
| Allowed to force push | On or off | Whether history can be rewritten |
The strictest setup uses "No one" for direct pushes and "Developers and Maintainers" for merging. Every change flows through a merge request.
Protect Another Branch
- Select Add protected branch.
- Pick a branch name or type a wildcard.
- Choose the merge and push roles.
- Select Protect.
Wildcards
An asterisk matches many branches at once.
| Pattern | Protects |
|---|---|
| release-* | release-1.0, release-2.0, and every other release branch |
| hotfix/* | Every branch under the hotfix folder |
| main | Only the branch named main |
See the Rule in Action
A developer pushes straight to a protected branch and meets this message.
$ git push origin main remote: GitLab: You are not allowed to push code to protected branches on this project. ! [remote rejected] main -> main (pre-receive hook declined)
The rejection pushes the developer toward the right path: create a feature branch and open a merge request.
git switch -c feature/new-footer git push -u origin feature/new-footer
Protected Branches in Pipelines
Protection links to pipeline security. CI/CD variables marked as protected reach jobs only on protected branches. A feature branch cannot read the production deploy token, even when someone edits the pipeline file.
Feature branch pipeline Protected main pipeline ┌───────────────────┐ ┌────────────────────────┐ │ Tests │ │ Tests │ │ No deploy secrets │ │ Deploy with secrets ✔ │ └───────────────────┘ └────────────────────────┘
Related Safeguards
| Feature | Where to Find It | Purpose |
|---|---|---|
| Protected tags | Settings → Repository | Stops changes to release tags |
| Merge request settings | Settings → Merge requests | Requires passing pipelines and resolved threads |
| Push rules | Settings → Repository | Checks commit messages and file names on paid plans |
| Code owners | CODEOWNERS file | Names experts for specific folders; enforced approval needs a paid plan |
Unprotect a Branch
Select Unprotect beside the branch in the list. Maintainers carry out this action. Think twice before unprotecting a branch that holds production code.
Recommended Setup for a Small Team
- Protect main with "No one" allowed to push.
- Allow Developers and Maintainers to merge.
- Turn off force push.
- Require a successful pipeline before merge.
- Protect release branches with the same rules.
Common Questions
| Question | Answer |
|---|---|
| Can a Maintainer bypass protection? | Only when the settings grant that role push access |
| Does protection stop a merge request? | No, merge requests remain the standard path |
| Does protection apply to local branches? | No, protection exists only on the GitLab server |
