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

  1. Open your project.
  2. Select Settings → Repository.
  3. Expand Protected branches.

The table lists each protected branch with its permissions.

Permission Options

SettingChoicesMeaning
Allowed to mergeMaintainers, Developers and Maintainers, No oneWho clicks Merge on a merge request
Allowed to push and mergeMaintainers, Developers and Maintainers, No oneWho pushes straight to the branch
Allowed to force pushOn or offWhether 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

  1. Select Add protected branch.
  2. Pick a branch name or type a wildcard.
  3. Choose the merge and push roles.
  4. Select Protect.

Wildcards

An asterisk matches many branches at once.

PatternProtects
release-*release-1.0, release-2.0, and every other release branch
hotfix/*Every branch under the hotfix folder
mainOnly 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

FeatureWhere to Find ItPurpose
Protected tagsSettings → RepositoryStops changes to release tags
Merge request settingsSettings → Merge requestsRequires passing pipelines and resolved threads
Push rulesSettings → RepositoryChecks commit messages and file names on paid plans
Code ownersCODEOWNERS fileNames 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

QuestionAnswer
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