Защищённая ветка: почему push в main отклонён
Обновлено 31 июля 2026 г.
Пытаешься отправить коммит прямо в main, а сервер отвечает отказом: ветка защищена, и писать в неё напрямую нельзя. Выглядит это так:
$ 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'Ключевые слова тут - protected branch и remote rejected. Коммиты собрались и уехали на сервер, но сервер отказался двигать ветку: не потому, что ты чего-то не знаешь, а потому, что на main заведено правило.
Это не «fetch first»
Отказ легко спутать с другим, куда более частым:
! [rejected] main -> main (fetch first)Это разные вещи. fetch first значит, что ты просто отстал: на сервере есть коммиты, которых у тебя нет, и лечится это связкой git pull, потом git push. Ветку примут, надо только подтянуть чужое.
protected branch - это запрет по правилу. Никакой pull тут не поможет: сколько ни синхронизируйся, прямой push в main всё равно отвергнут. Путь один - через pull request: заведи ветку, отправь её, открой PR, и код попадёт в main через слияние, а не напрямую.
Что защищает такая настройка
Смысл в том, что в main попадает только просмотренный и собранный код. С этой ветки собирают релиз и от неё отводят новые ветки, поэтому сломанный main останавливает всю команду. Правило закрывает прямую дорогу и оставляет одну - через ревью.
Обычно к нему добавляют ещё несколько условий на слияние:
- Обязательная проверка CI. Пока сборка и тесты не отметились зелёной галочкой, кнопка слияния заблокирована. Красный крестик - слить нельзя.
- Обязательный ревьюер. Нужен чужой approve, свою же ветку сам себе влить не дадут. Кто-то ещё должен прочитать diff.
- Запрет force push. git push --force в
mainотвергается тоже: переписать общую историю нельзя даже тому, у кого есть права на запись.
Всё это настройка хостинга, а не самого git. Правило живёт в GitHub, GitLab или на другом сервере, в разделе про защиту веток. У себя на машине никаких protected branch нет: локально ты пушишь в свою ветку и коммитишь в main сколько угодно. Отказ приходит только от сервера и только на push.
Частые ошибки
Ответить на protected branch командой git pull, как на fetch first. Синхронизация тут ничего не меняет: правило не про отставание, а про запрет прямого push. Смотри на текст в скобках: fetch first и protected branch hook declined лечатся по-разному.
Пытаться обойти защиту через --force. Force push в защищённую ветку сервер отвергает так же, а часто и жёстче: правило ровно для того и заведено, чтобы историю main нельзя было переписать в обход ревью.
Где это в учебнике
Feature branch workflow и правило «в main - только через pull request» разобраны в седьмой главе.