Why GitLab says you're not allowed to push to a protected branch, and the fix
Short answer
GitLab rejects a push with "You are not allowed to push code to protected branches on this project" when the branch is protected and your role isn't in its Allowed to push and merge list. The default branch is protected by default, and under the default Fully protected level only Maintainers can push to it or merge into it. Push your work to a new branch and open a merge request, or ask a Maintainer to change the rule in Settings › Repository › Branch rules. Force pushes to a protected branch are rejected unless the rule turns on Allowed to force push.
You push, and GitLab answers with a rejected push:
remote: GitLab: You are not allowed to push code to protected branches on this project.
! [remote rejected] main -> main (pre-receive hook declined)
The branch is protected, and your role isn’t allowed to push to it. That’s usually on purpose: protected branches are how a project makes changes go through merge requests. Here is what each of GitLab’s protected-branch errors means in 2026, who can push and merge by default, and how to fix it.
The errors, and what to do
| GitLab says | What happened | Fix |
|---|---|---|
| You are not allowed to push code to protected branches on this project. | You pushed to a protected branch, and your role isn’t in its Allowed to push and merge list | Push to a new branch and open a merge request, or ask a Maintainer to change the rule |
| You are not allowed to force push code to a protected branch on this project. | You force pushed, after a rebase or an amend, and the rule doesn’t allow force pushes | Push to a new branch, or ask for Allowed to force push |
| You are not allowed to merge code into protected branches on this project. | GitLab was writing a merge into the branch for you, and found you may neither merge nor push there. It’s rare: GitLab usually refuses earlier with “You are not allowed to merge this merge request” | Ask someone allowed to merge to merge it |
| You cannot push the initial commit because the default branch is protected and your role does not allow it. | You pushed the first commit to an empty project | Ask a Maintainer to push the first commit, or a group Owner or administrator to set the initial protection to Fully protected after initial push |
| You are not allowed to push code to this project. | Your role can’t push to any branch | Ask for the Developer role or higher |
| You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch. | You tried to delete a protected branch without the Maintainer or Owner role | Ask a Maintainer or Owner |
| You can only delete protected branches using the web interface. | A Maintainer or Owner tried to delete it with Git | Delete it in Code › Branches |
The usual fix: a merge request
Put your commits on a new branch and open a merge request from it, in one push (more ways to do that from the terminal):
git switch -c my-fix
git push -o merge_request.create -o merge_request.target=main origin my-fix
Your local main still has the commits you couldn’t push. Once the merge request is open, git switch main && git reset --hard origin/main brings it back in line; the commits live on my-fix. The reset throws away uncommitted changes, so commit or stash them first.
Who can push and merge by default
The default branch is protected by default. Administrators set the starting level for an instance, and group Owners for a group:
| Protection level | Push | Merge | Force push |
|---|---|---|---|
| Fully protected (the default) | Maintainers | Maintainers | No one |
| Fully protected after initial push | Maintainers; Developers can push the first commit | Maintainers | No one |
| Protected against pushes | Maintainers | Developers and Maintainers | No one |
| Partially protected | Developers and Maintainers | Developers (through their push access) and Maintainers | No one |
| Not protected | Developers and Maintainers | Developers and Maintainers | Allowed |
So under the default, a Developer can’t merge into the default branch either. Once every merge check passes, their merge request says “Ready to merge by members who can write to the target branch.” instead of showing Merge.
Change a branch rule
A Maintainer or Owner can change the project’s branch rules. Rules set for a whole group are changed by the group’s Owner, and on Premium and Ultimate a rule can limit who may unprotect or edit it. In the project:
- Select Settings › Repository, then expand Branch rules.
- Next to the branch, select View details.
- Edit Allowed to merge and Allowed to push and merge, and turn Allowed to force push on or off.
| Setting | Controls |
|---|---|
| Allowed to merge | Who can merge changes through merge requests |
| Allowed to push and merge | Who can push directly, and who can also merge |
Two common setups:
- Everything through merge requests: Allowed to merge = Developers + Maintainers, Allowed to push and merge = No one.
- Direct pushes allowed: Allowed to push and merge = Developers + Maintainers.
Anyone allowed to push can skip the merge request, and with it the approval rules. On Premium and Ultimate, Require code owner approval doesn’t change that: it’s a merge request check, so to make Code Owners review every change, set Allowed to push and merge to No one (see GitLab CODEOWNERS explained).
Deleting a protected branch
Only users with the Maintainer or Owner role can, and only in the web interface or the API: in Code › Branches, select More actions next to the branch, then Delete protected branch, and confirm with the branch name. git push --delete is rejected. The default branch can’t be deleted at all; make another branch the default first.
Merging from your phone
MergeBell signs in with your own GitLab token, so branch rules apply exactly as they do on the web. Its merge sheet lists what’s still blocking a merge before you tap Merge, and approve, merge, squash and auto-merge are on the free tier. If your merge request can’t merge yet, why can’t I merge my GitLab merge request? covers the other reasons.
Frequently asked questions
What does "You are not allowed to push code to protected branches on this project" mean?
The branch you pushed to is protected, and your role isn't in its Allowed to push and merge list. Push your commits to a new branch and open a merge request, or ask a Maintainer or Owner to change the branch rule in Settings › Repository › Branch rules.
Why can't a Developer merge into main in GitLab?
The default branch is protected by default, and the default protection level, Fully protected, allows only Maintainers to push to it and to merge into it. A Maintainer can add Developers to the branch's Allowed to merge list. Until then, once every merge check passes, the merge request says it's ready to merge by members who can write to the target branch, instead of showing Merge.
How do I allow force push to a protected branch in GitLab?
A Maintainer or Owner opens Settings › Repository › Branch rules, selects View details next to the branch, and turns on Allowed to force push. Without it, GitLab rejects force pushes to that branch, for example after a rebase.
What is the difference between Allowed to merge and Allowed to push and merge?
Allowed to merge controls who can merge changes into the branch through merge requests. Allowed to push and merge controls who can push to it directly, and also lets them merge. To make everyone use merge requests, set Allowed to merge to Developers + Maintainers and Allowed to push and merge to No one.
How do I delete a protected branch in GitLab?
Only users with the Maintainer or Owner role can, and only in the web interface or the API: in Code › Branches, select More actions next to the branch, then Delete protected branch, and confirm with the branch name. Deleting it with git push fails.
Sources
- GitLab docs — Protected branches
- GitLab docs — Default branch: protect initial default branches
- GitLab docs — Rebase and force push
- GitLab docs — Roles and permissions
- GitLab docs — Push options
Checked against these pages on 24 October 2026. GitLab changes quickly — if something here no longer matches, tell us and we will fix it.
Do this from your phone with MergeBell
Free for the whole review loop: the To-Do inbox, diffs and line comments, approve and merge, pipelines with retry, and push alerts for your To-Dos. Works with gitlab.com and self-managed GitLab 16.0+.
Get MergeBell for AndroidiPhone: email me at launch
On Google Play for Android 12 or later. The iPhone app is coming soon to the App Store. An independent app, not affiliated with GitLab Inc.