Код-ревью и защита веток
Урок про то, как устроить ревью кода через Pull Request и техническими средствами не дать влить в основную ветку непроверенный код.
Branch protection — правила на стороне платформы (GitHub/GitLab), которые запрещают вливать в защищённую ветку код, пока не выполнены условия: пройдено ревью и зелёные проверки.
Зачем процесс, а не «просто посмотреть код»
Код-ревью «по доброй воле» не работает: под дедлайн его пропускают, в main пушат напрямую, баги уходят в прод. Поэтому ревью делают обязательным этапом, который нельзя обойти технически. Pull Request (на GitHub) или Merge Request (на GitLab) — это и есть единица ревью: ветка с изменениями, обсуждением и набором автоматических проверок, которую невозможно слить, не выполнив правила.
Pull Request как процесс
Жизненный цикл PR обычно такой: автор пушит ветку и открывает PR → запускается CI → ревьюеры читают diff, оставляют комментарии и запрашивают правки → автор отвечает коммитами → когда есть аппрув и проверки зелёные, PR вливается. Хороший PR маленький и сфокусированный: ревьюеру проще внимательно прочитать 200 строк, чем 2000. Не менее важно качественное описание: что изменилось, зачем, как проверить, на что обратить внимание. Описание экономит ревьюеру десятки минут на реконструкцию контекста и часто становится частью истории — особенно при squash-слиянии, когда текст PR уходит в коммит и changelog.
Ревью — это ещё и канал распространения знаний. Когда второй человек читает чужой код, по команде расходится понимание того, как устроена система; снижается «фактор автобуса», находятся не только баги, но и более простые решения. Поэтому ревью оставляют даже там, где автор технически мог бы влить сам: ценность не только в ловле ошибок, но и в общей ответственности за код. Комментарии при этом полезно разделять на блокирующие («так нельзя, поправь») и необязательные («nit: можно красивее») — это ускоряет договорённость и не превращает ревью в бесконечный спор о вкусах.
git checkout -b feat/search-filters
# ... работаем ...
git push -u origin feat/search-filters
# через GitHub CLI можно открыть PR прямо из терминала
gh pr create --fill --base main
gh pr view --web
Required reviews: обязательные аппрувы
Правило «требуется N аппрувов» не даёт влить PR, пока его не одобрит нужное число ревьюеров. Полезные настройки:
- минимум аппрувов (часто 1–2);
- dismiss stale approvals — сбрасывать одобрение, если после него запушены новые коммиты (иначе аппрувнут одно, а вольют другое);
- require review from Code Owners — обязательно одобрение владельца затронутого кода.
CODEOWNERS: кто отвечает за код
Файл CODEOWNERS (в корне, в .github/ или docs/) сопоставляет пути с ответственными людьми/командами. Если PR трогает эти файлы, платформа автоматически назначит владельцев ревьюерами, а при включённом правиле — потребует их аппрув.
# синтаксис: путь владельцы
* @org/core-team
/frontend/ @org/frontend-team
/backend/billing/ @alice @bob
*.sql @org/dba
Так нельзя случайно изменить биллинг или схему БД без участия тех, кто за них отвечает. Правила читаются сверху вниз, и побеждает последнее совпавшее: общая строка * задаёт владельцев по умолчанию, а более конкретные пути ниже переопределяют их для своих участков. Это удобно в больших репозиториях, где у каждого модуля своя команда: ревью автоматически попадает к тем, кто реально разбирается в затронутой области, а не к случайному дежурному. Важно держать файл в актуальном состоянии — устаревший CODEOWNERS назначает ревьюерами людей, давно ушедших из команды, и блокирует PR.
Status checks: зелёный CI как пропуск
Status checks — это внешние проверки (тесты, линтер, сборка, сканер безопасности), которые сообщают платформе свой статус. В branch protection можно сделать конкретные проверки обязательными: пока они не «зелёные», кнопка слияния заблокирована. Это и есть техническое воплощение идеи «main всегда зелёный» из предыдущих уроков: ни один PR с падающими тестами просто не доедет до основной ветки, какой бы срочной ни была задача. Часто включают и require branches to be up to date — PR должен содержать свежий main, чтобы проверки шли на актуальном коде. Без этого возможна коварная ситуация: ваш PR зелёный, соседний зелёный, но вместе после слияния они конфликтуют по смыслу, и main ломается, хотя каждый по отдельности проходил.
# .github/workflows/ci.yml — этот workflow становится status check
name: ci
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
Имя job (test) появится в списке проверок PR; его и отмечают обязательным в настройках ветки.
Draft PR: ранняя обратная связь без «зелёного света»
Иногда нужно показать направление до готовности. Draft (черновой) PR помечается как «ещё не для слияния»: его нельзя замёржить и обычно он не дёргает ревьюеров уведомлениями, но CI и обсуждение уже доступны. Когда работа готова — переводят в обычный статус («Ready for review»).
gh pr create --draft --fill
# когда готово:
gh pr ready
Как это работает под капотом
Защита ветки — это серверная политика платформы, а не функция самого Git. Технически она навешивается на операцию обновления ссылки (ref) refs/heads/main: попытка запушить напрямую или слить PR, не выполнив условия, отклоняется ещё до изменения указателя ветки. Поэтому правила нельзя обойти с локальной машины — решение принимает сервер. Status checks работают через статусы коммита (commit status / check run), которые CI выставляет по API; платформа просто читает их и решает, разблокировать ли слияние. CODEOWNERS платформа парсит как набор glob-правил и сопоставляет с файлами в diff.
Частые ошибки
- Защита только UI, но push не запрещён. Если разрешён прямой
git pushвmain, весь процесс PR обходится одной командой. Запрет прямого пуша обязателен. - Не сбрасывать устаревшие аппрувы. Без dismiss stale approvals можно получить аппрув, а потом дослать любой код — ревью становится фикцией.
- Включить администраторам обход. Если
main«защищён, но не для админов», правило регулярно нарушается «по-быстрому». Включайте include administrators. - Обязательные проверки без require up-to-date. PR могут протестировать на устаревшей базе, и поломка от свежего
mainпросочится. - Гигантские PR. 3000 строк никто не ревьюит внимательно — аппрув ставят «не глядя». Дробите изменения.
- Self-approve вместо ревью. Одобрять собственный PR — значит превращать защиту в формальность; требуйте аппрув другого человека.
Итоги
- Pull/Merge Request — это единица ревью: diff + обсуждение + автоматические проверки.
- Branch protection делает ревью неотменяемым на стороне сервера, а не «по договорённости».
- Required reviews + dismiss stale approvals не дают влить неодобренный или подменённый код.
- CODEOWNERS назначает ответственных за пути и может требовать их аппрув.
- Status checks превращают зелёный CI в обязательный пропуск к слиянию.
- Draft PR даёт раннюю обратную связь без риска преждевременного мёржа.