# GitHub flow: малі гілки, швидкі мерджі

> Цикл, у якому працює більшість продуктових команд: гілка від main, pull request, рев'ю й перевірки, мердж, деплой. Чому малі короткоживучі гілки безпечніші, що означають «змерджено» і «викладено», як фіча-флаги дають викласти незавершену роботу прихованою і як читати прогрес фічі зі списку pull requests.

- Курс: [Git і GitHub для продактів](https://productovi.com/uk/courses/git-for-product.md)
- Модуль: Командні воркфлоу
- Урок 10/15, ~41 хв
- Джерело: https://productovi.com/uk/courses/git-for-product/github-flow

## Це вже на сайті?

**Alex Tutor:** П'ятниця в Котокормі, одразу після зустрічі твоєї продуктової команди. Яке питання сьогодні звучало найчастіше?

**Sofia:** «Це вже на сайті?» Тричі. Один раз про виправлення кнопки оформлення, двічі про банер осіннього розпродажу від Emma.

**Alex Tutor:** Тоді складімо весь шлях зміни на одну картинку. У команди для нього є назва: **GitHub flow**. Кожен крок тобі вже знайомий, просто досі не було нагоди побачити їх усі разом.

```text
Граф комітів, від найстарішого: main за останні два тижні
1. коміт e7c3b19 у main "Add summer promo banner"
2. гілка content/delivery-copy починається від коміту e7c3b19
3. коміт e19c3b7 у content/delivery-copy "Rewrite delivery page copy"
4. коміт f02a6d4 у main "Update FAQ answers"
5. гілка fix/checkout-button починається від коміту f02a6d4
6. коміт 3a9d1c4 у fix/checkout-button "Reproduce bug in a test"
7. коміт 8be2f70 у main "Add cat treats bundle"
8. гілка feature/free-delivery-1000 починається від коміту 8be2f70
9. коміт 5c1d7e2 у feature/free-delivery-1000 "Set freeDeliveryFrom to 1000"
10. коміт a8f40b9 у feature/free-delivery-1000 "Update delivery page text"
11. коміт d36b9c5 у feature/free-delivery-1000 "Update cart hint text"
12. коміт b7e4a05 у fix/checkout-button "Re-enable button after cart edits"
13. коміт 6f2c8a1: feature/free-delivery-1000 змерджено в main через squash "Raise free-delivery threshold to 1000 UAH (#133)"
14. мердж-коміт c90d4e7: main змерджено в content/delivery-copy "Merge branch 'main' into content/delivery-copy"
15. коміт a7d93e4: content/delivery-copy змерджено в main через squash "Rewrite delivery page copy (#132)"
16. коміт c2d7f90 у fix/checkout-button "Update checkout hint copy"
17. коміт f7a2b61 у fix/checkout-button "Restore checkout button colour"
18. мердж-коміт 9e3b5d2: main змерджено в fix/checkout-button "Merge branch 'main' into fix/checkout-button"
19. коміт d51c7e8: fix/checkout-button змерджено в main через squash "Fix checkout button after cart edits (#134)" (виділено)
```

*Три зміни, три короткі гілки. Кожна почалася від main, пройшла через pull request і повернулася одним squash-комітом. Кожен мердж у main викладали на сайт за кілька хвилин.*

**Sofia:** Текст Emma, поріг від Daniel, виправлення кнопки від Daniel. Жодна з цих гілок не прожила довше приблизно тижня.

**Daniel:** У цьому й суть. `main` завжди є версією, яку можна викласти на сайт просто зараз. Усе незавершене чекає у своїй гілці або, як побачиш сьогодні, за перемикачем.

**Alex Tutor:** Тож цикл короткий: маленька гілка від `main`, pull request, мердж, деплой. А наступна зміна знову стартує від свіжої `main`.

![Петля конвеєрів: посилка з кормом виїжджає з бічного відсіку, потрапляє на головну стрічку, минає пункт перевірки й заїжджає у фургон, а наступна вже стартує.](https://productovi.com/courses/git-for-product/inline/github-flow-illustration-2.webp)

> **Вправа:** Розстав кроки GitHub flow у Котокормі по порядку: від ідеї до моменту, коли клієнти бачать зміну.

## Змерджено, потім викладено

**Sofia:** У середу Daniel сказав «дай йому п'ять хвилин». Що відбувається за ці п'ять хвилин?

**Daniel:** Воркфлоу GitHub Actions бере нову `main`, збирає сайт і викладає його на наші сервери. Це і є **деплой** (викладання). Така сама задача, як `build` і `test`, тільки запускається на `main` після мерджу.

```text
#134 у середу зранку
- [Merged] Fix checkout button after cart edits #134: Змерджено в main о 9:40 як d51c7e8
- [All checks have passed] deploy (production): Запускався на d51c7e8 у main, завершився о 9:44
```

**Alex Tutor:** Отже, «змерджено» і «викладено» це дві різні події. У Котокормі між ними кілька хвилин, і друга настає сама після першої. В інших командах між ними бувають тижні.

**Alex Tutor:** Це можна перевірити, нікого не питаючи. Станом на 2026 рік на сторінці репозиторію в правій колонці є розділ `Deployments` («деплої»). Натисни `production`, і побачиш, який коміт зараз на сайті й відколи.

**Sofia:** А якщо деплой упаде?

**Daniel:** Тоді зміна є в `main`, а на сайті її немає. Ми отримуємо сповіщення і або одразу виправляємо, або робимо revert. Зламана `main` блокує наступний деплой для всіх, тому це завжди першочергове.

**Sofia:** Тож перш ніж казати підтримці, що щось уже на сайті, я дивлюся `production` у `Deployments`.

**Alex Tutor:** І ще раз дивишся на сам живий сайт. Деплой каже, що код прибув; а що він працює, покажуть лише власні очі.

> **Вправа:** Котокорм автоматично викладає кожен мердж у `main`; деплой триває кілька хвилин. Тієї ж миті, коли #134 показує `Merged`, кожен клієнт уже бачить виправлення на сайті.

**Alex Tutor:** Daniel згадав про невдалі деплої. Ось як це виглядає з боку клієнта.

> **Вправа:** Pull request #160 з новим текстом сторінки доставки показує `Merged`. За хвилину деплой у `production` падає. Що бачать клієнти на сторінці доставки?

## Малі й короткоживучі

**Sofia:** А навіщо тримати гілки такими короткими? Хіба не простіше зробити всю фічу й змерджити один раз?

**Alex Tutor:** Пам'ятаєш `feature/loyalty-points`? Дванадцять комітів попереду, 86 позаду, п'ять місяців без змін. Ось на що зазвичай перетворюється «змерджимо один раз, наприкінці».

**Daniel:** Кожен день, поки гілка живе, `main` іде вперед без неї. Що більше відставання, то більше шансів на конфлікти або на сюрприз, як із моєю кнопкою в березні.

**Alex Tutor:** Малі pull requests ще й переглядають швидше та уважніше. Сорок змінених рядків це десять уважних хвилин. Дві тисячі чекають, поки в когось звільниться пів дня, а потім їх проглядають по діагоналі.

**Daniel:** А ще їх легше скасувати. Якщо одна маленька зміна щось ламає, `Revert` прибирає саме її. Відкотиш величезну, і разом із поганою зміною підуть десять добрих.

**Sofia:** Тобто «мало» тут не про охайність. Це менше ризику на кожен мердж.

![Робітник по одній переносить невеликі легкі коробки через вузький місток, а інший ледве втримує на ньому величезний хиткий ящик.](https://productovi.com/courses/git-for-product/inline/github-flow-illustration-3.webp)

*Невеликі pull request швидше перевіряють і легше відкочують.*

**Alex Tutor:** Саме так. Орієнтир, яким користується багато команд: гілка живе кілька днів, а pull request можна переглянути за один присід.

> **Вправа:** Чому в Котокормі воліють малі pull requests у короткоживучих гілках? Познач усе, що підходить.

**Sofia:** А чи можу я помітити таку гілку, поки вона ще не стала проблемою?

**Alex Tutor:** Так, на сторінці гілок. Дивися на дві речі: коли гілку востаннє оновлювали і наскільки вона відстає від `main`. Стара й далеко позаду: ось тривожний знак.

**Daniel:** І на її pull request. Якщо `Files changed` показує 60 файлів для «невеликої правки», спитай чому. Питання на початку обходиться дешевше, ніж болісне рев'ю наприкінці.

**Alex Tutor:** На графі та сама історія: довга доріжка, що почалася десь угорі, поки `main` поруч збирала коміти.

> **Вправа:** Для обох гілок ось-ось відкриють pull request. Яке твердження найкраще відповідає GitHub flow?

**Alex Tutor:** Стара гілка лояльності і є тим тривожним знаком. То як її перебудувати?

> **Вправа:** Бали лояльності треба перебудувати на свіжій `main`. Який план відповідає GitHub flow?

## Змерджити зараз, увімкнути пізніше

**Sofia:** Тепер банер Emma. Розпродаж стартує в понеділок. Якщо змерджити сьогодні, банер з'явиться сьогодні й анонсуватиме розпродаж, який ще не почався.

**Alex Tutor:** А якщо чекати до понеділка зранку, рев'ю, мердж і деплой відбуватимуться поспіхом, коли клієнти вже приходять.

**Daniel:** Для цього й існує **фіча-флаг** (feature flag): перемикач навколо частини сайту. Код уже в `main` і викладений, але банер видно лише тоді, коли флаг увімкнено.

![У вітрині крамниці висить повністю встановлена, але темна рамка банера; поруч рука тягнеться до вимкненого настінного вимикача.](https://productovi.com/courses/git-for-product/inline/github-flow-illustration-4.webp)

*З фіча-флагом «задеплоєно» і «видно покупцям» — два окремі моменти.*

**Alex Tutor:** У Котокормі перемикачі живуть в окремій панелі налаштувань флагів, поза репозиторієм. Щоб увімкнути флаг, не потрібні ні pull request, ні деплой.

**Daniel:** Я додав перевірку в гілку Emma: флаг `autumn-sale-banner`, за замовчуванням вимкнений. Emma позначила #136 як готовий до рев'ю, я схвалив, і годину тому вона його змерджила.

> **Вправа:** У суботу клієнт відкриває головну сторінку Котокорму. Що він бачить?

**Alex Tutor:** Ще одне про ранок понеділка. Правда чи ні?

> **Вправа:** Щоб у понеділок о 8:00 показати банер розпродажу, Emma в Котокорму має відкрити pull request, який вмикає флаг `autumn-sale-banner`, і дочекатися деплою.

**Sofia:** Тобто банер уже на сайті, але його ніхто не бачить.

**Alex Tutor:** Змерджено, викладено, приховано. У понеділок о 8:00 Emma вмикає флаг, і клієнти бачать банер за лічені секунди. Якщо щось не так, вона його вимикає, знову без деплою.

![Банер розпродажу змерджили й виклали в п'ятницю за флагом, тож клієнти нічого не бачили, доки флаг не ввімкнули в понеділок о 8:00.](https://productovi.com/courses/git-for-product/diagrams/m4-l1-merged-deployed-visible-uk.png)

**Daniel:** А ще флаги дають змерджити незавершену роботу. Недобудована частина лишається вимкненою, тож `main` і далі готова до викладання, поки фіча росте малими pull requests.

**Alex Tutor:** Один нюанс: кожен флаг це додаткове «якщо» в коді. Коли фічу ввімкнено назавжди, флаг треба прибрати, інакше код заростає забутими перемикачами.

**Sofia:** Щойно хтось із маркетингу побачить, що #136 змерджено, мене запитають, чи банер уже на сайті.

**Alex Tutor:** Тоді відповідай так, щоб не можна було зрозуміти хибно. «Так» буде неправдою, а «ні» лише половиною правди.

**Daniel:** І, будь ласка, назви час. Під нього планують розсилки.

**Alex Tutor:** Два-три речення, як відповідь у чаті.

> **Вправа:** Колега з маркетингу пише: «#136 змерджено, тож банер розпродажу вже на сайті? Можна сьогодні ввечері відправити розсилку?» Розпродаж стартує в понеділок; флаг `autumn-sale-banner` вимкнено, Emma вмикає його в понеділок о 8:00. Напиши відповідь у 2–3 реченнях.

## Бали лояльності, друга спроба

**Sofia:** Сьогодні CEO знову питав про бали лояльності. Може, Daniel просто змерджить стару гілку?

**Daniel:** Ні в якому разі. Вона відстає на 86 комітів, і половина того, що вона зачіпає, відтоді змінилася. Я перебудую фічу на свіжій `main` малими pull requests, і все за одним флагом: `loyalty-points`.

**Alex Tutor:** Кожен шматок мерджать і викладають окремо, непомітно для клієнтів. «Запущеною» фіча стане лише того дня, коли флаг для них увімкнуть.

**Daniel:** Можеш накидати, як ми це поріжемо? Ти знаєш, що клієнтам потрібно насамперед. А я скажу, що технічно можливо.

**Sofia:** Тоді план нарізки: шматки, їхній порядок, що лишається прихованим і коли ми вважаємо фічу запущеною.

> **Вправа:** Склади план нарізки балів лояльності для GitHub flow.

## Фіча у списку pull requests

**Alex Tutor:** Середа наступного тижня. Команда взяла твій план і додала мітку `loyalty`. Відфільтруй за нею pull requests, і прогрес фічі видно сам собою.

```text
Pull requests з міткою loyalty
- [Merged] Add loyalty points behind a flag #155: автор Daniel · змерджено у вівторок · флаг loyalty-points: вимкнено
- [Open] Earn points on paid orders #156: автор Daniel · Review required · перевірки пройдено
- [Draft] Write loyalty programme page #157: авторка Emma · Draft
```

**Sofia:** Один шматок уже в `main` і на сайті, але прихований. Один чекає на рев'юера. Сторінка Emma поки чернетка.

**Daniel:** І саме тому ще ніхто не повинен нічого анонсувати, хоча код лояльності на сайті вже з вівторка.

**Alex Tutor:** Список pull requests показує, наскільки просунулося будівництво. Флаг показує, що бачать клієнти. Щоб відповісти «де зараз фіча?», продакт читає і те, і інше.

**Sofia:** А змерджений pull request із вимкненим флагом означає «зроблено й приховано», а не «запущено».

> **Вправа:** Зістав кожну ознаку, яку видно про бали лояльності, з тим, що вона означає.

**Alex Tutor:** Це і є GitHub flow: `main` завжди готова до викладання, малі гілки, pull request для всього, деплой після мерджу і флаги для всього, що ще не готове для клієнтів.

**Sofia:** Сьогодні підтримка спитала, в якій версії вийшло виправлення кнопки. У нас же немає версій?

**Daniel:** Поки що ні. Деякі команди живуть номерами версій і релізними гілками. На наступному уроці побачиш таку, і чому ми так не працюємо.

- Попередній урок: [Іконки, кольори й перевірки: що означає кожен стан GitHub](https://productovi.com/uk/courses/git-for-product/icons-and-colours.md)
- Наступний урок: [Git flow: гілки develop, release і hotfix](https://productovi.com/uk/courses/git-for-product/git-flow.md)

---
Productovi Learning. Безкоштовно, читати можна без реєстрації.
