A protected branch: why the push to main is rejected

Updated July 31, 2026

You try to push a commit straight into main, and the server refuses: the branch is protected, and you cannot write to it directly. It looks like this:

$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 312 bytes | 312.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Changes must be made through a pull request.
To github.com:team/proj.git
 ! [remote rejected] main -> main (protected branch hook declined)
error: failed to push some refs to 'github.com:team/proj.git'

The words that matter are protected branch and remote rejected. The commits were packed and sent to the server, but the server refused to move the branch: not because you are missing something, but because there is a rule on main.

This is not "fetch first"

The refusal is easy to confuse with a far more common one:

 ! [rejected]        main -> main (fetch first)

These are different. fetch first means you are simply behind: the server has commits you do not, and the cure is git pull, then git push. The branch would be accepted; you just have to pull the others' work in first.

protected branch is a refusal by rule. No pull helps here: however much you sync, a direct push to main is still rejected. There is one path, through a pull request: branch off, push the branch, open a PR, and the code reaches main through a merge instead of directly.

What the setting protects

The point is that only reviewed, built code lands in main. Releases are cut from that branch and new branches start from it, so a broken main stops the whole team. The rule closes the direct road and leaves one open, through review.

A few more conditions on the merge usually come with it:

  • A required CI check. Until the build and tests report a green check, the merge button is locked. A red cross means you cannot merge.
  • A required reviewer. Someone else's approve is needed, and you are not allowed to merge your own branch by yourself. Another person has to read the diff.
  • No force push. git push --force into main is rejected too: nobody may rewrite the shared history, write access or not.

All of this is a hosting setting, not git itself. The rule lives in GitHub, GitLab or another server, under branch protection. On your own machine there is no protected branch: locally you push to your own branch and commit to main as much as you like. The refusal comes only from the server, and only on push.

Common mistakes

Answering protected branch with git pull, as if it were fetch first. Syncing changes nothing here: the rule is not about being behind, it is about forbidding a direct push. Read the text in the parentheses: fetch first and protected branch hook declined are cured in different ways.

Trying to get around the protection with --force. The server rejects a force push into a protected branch just the same, often harder: the rule exists precisely so the history of main cannot be rewritten around review.

Where this is in the book

The feature branch workflow and the "into main only through a pull request" rule are covered in chapter 7.

Chapter 7. How teams actually use git