Захист гілки перетворює домовленості («не пушимо в main», «зливаємо лише після рев'ю й зелених тестів») на правила, які платформа примусово виконує.
Типовий набір правил для main:
- заборонити прямий push - зміни лише через PR;
- обов'язкове схвалення (1-2 рецензенти) і рев'ю власників коду (CODEOWNERS);
- скидати схвалення при нових комітах (dismiss stale approvals) - інакше після апруву можна дописати що завгодно;
- обов'язкові перевірки статусу (required status checks): тести, Pint, PHPStan мають бути зеленими;
- гілка має бути актуальною перед злиттям - або merge queue замість цього;
- заборонити force push і видалення гілки;
- розв'язані обговорення перед злиттям, за потреби - підписані коміти і лінійна історія.
Branch protection rules проти rulesets:
| Branch protection | Rulesets | |
|---|---|---|
| скільки діє на гілку | одне правило | кілька наборів одночасно, правила агрегуються |
| конфлікт налаштувань | - | діє найсуворіший варіант |
| вимкнути тимчасово | лише видалити | статус Disabled без видалення |
| хто бачить | адміністратори | усі з доступом на читання |
| винятки | обмежено | явний список bypass (ролі, команди, GitHub Apps) |
| рівень організації | ні | так (на планах Team/Enterprise) |
Обидва механізми працюють разом: застосовуються всі правила, що підходять.
Пастки:
- назва обов'язкової перевірки має збігатися з назвою job у CI. Перейменували job - PR зависає в очікуванні перевірки, яка ніколи не прийде;
- перевірка, що запускається не завжди (через
pathsу workflow), лишається «очікуваною» - PR не можна злити. Рішення - job, що завжди звітує успіхом, якщо змін немає; - адміністратори за замовчуванням можуть обходити правила - варто вирішити свідомо;
- bypass для ботів (релізний бот) - лише конкретним GitHub Apps, не всім.
Правила як код: rulesets можна експортувати й імпортувати в JSON чи керувати ними через API й Terraform - однакові правила для десятків репозиторіїв.