Git-стратегія гілкування
Git-стратегія гілкування — це домовленість про те, як команда розділяє роботу на гілки і як знову їх зводить. Вибір виглядає справою смаку, але нею не є: єдина змінна, що надійно передбачає біль, — скільки живе гілка до злиття, і кожна стратегія насправді є позицією щодо цього одного числа. На цій сторінці — чотири моделі, які вам трапляться, що робить короткі гілки можливими і коли релізні гілки справді виправдовують свою ціну.
- Що важливо
- Час життя гілки
- Trunk-based
- Менше 24 годин
- Корелює з
- Elite-показниками DORA
Час життя гілки — це і є вся суть
Гілка — це ставка на те, що решта кодової бази не зміниться так, щоб конфліктувати з вашою роботою. Ця ставка дешева на день і дорога на місяць, бо ризик конфлікту зростає і з розміром вашої зміни, і з кількістю змін, які всі інші вливають, поки вас немає.
Пастка в тому, що витрата невидима, поки накопичується. Гілка, відкрита три тижні, кожен із цих днів відчувається продуктивною; ціна приходить одразу при злитті — як розв’язання конфліктів, якого ніхто не оцінював, і регресія, якої ніхто не передбачав. Саме тому довгоживучі гілки й болісна інтеграція — це одна проблема, описана двічі.
Чотири моделі, які вам трапляться
Trunk-based
Усі комітять в одну головну гілку через короткі гілки, що живуть години, а не дні. Незавершена робота ховається за прапорцями, а не в гілці. Production — це тег або деплой із main.
GitHub Flow
Одна головна гілка плюс гілка на зміну, що зливається через pull request, деплой із main. Прагматична середина й типовий вибір більшості продуктових команд — trunk-based із доданим рев’ю.
GitLab Flow
GitHub Flow плюс низхідні гілки, що віддзеркалюють середовища (staging, production) або версії. Зміни завжди течуть в один бік, main → нижче, тож середовище ніколи не міститиме того, чого немає в main.
GitFlow
Довгоживучі гілки develop, release і hotfix поруч із main. Створений для версійованого софту з кількома підтримуваними релізами «в полі» — і має відповідну ціну.
Важливе уточнення, бо GitFlow досі викладають як стандарт: його автор додав до оригінального допису 2010 року примітку, що модель створювалася для софту з явними версійованими релізами, і що командам, які роблять вебзастосунки з безперервною поставкою, не варто її брати. Вона ніколи не була хибною — вона відповідала на питання, якого більшість вебкоманд уже не має.
GitLab Flow варто знати, бо саме до нього зазвичай тягнуться, коли GitHub Flow перестає пасувати: коли є staging, який має бути рівно на крок позаду production, або клієнт на старішій версії. Його єдине правило запобігає класичній катастрофі — виправленню, внесеному прямо в production-гілку й ніколи не влитому назад, яке тихо повертається багом у наступному релізі.
Як обрати між ними
| Модель | Життя гілки | Пасує | Потребує |
|---|---|---|---|
| Trunk-based | < 1 дня | Безперервна поставка, одна жива версія | Надійні тести, feature flags |
| GitHub Flow | 1–3 дні | Більшість продуктових команд | Код-рев’ю, CI на кожен PR |
| GitLab Flow | 1–3 дні + гілки середовищ | Ступеневі середовища або кілька версій | Дисципліну: зміни течуть лише вниз |
| GitFlow | Тижні | Версійований чи встановлюваний софт | Реліз-менеджмент, беквпорти |
Чесне правило вибору коротке. Якщо ви підтримуєте рівно одну версію в production, беріть найкоротші гілки, які витримає ваш набір тестів. Якщо ви підтримуєте кілька версій одночасно — on-premise продукт, мобільний застосунок із користувачами на старих збірках, прошивка, — вам справді потрібні релізні гілки, і GitFlow тут розумна відповідь, а не спадкова звичка.
Варто знати ціну цієї відповіді, перш ніж на неї погодитися. Кожна підтримувана версія — це гілка, до якої виправлення безпеки треба застосувати окремо, окремо протестувати й окремо випустити. Три підтримувані версії означають, що кожен терміновий патч — це три cherry-pick, три прогони тестів і три релізи, а виправлення, правильне на main, іноді не лягає чисто на дворічну гілку. Ця робота і є справжньою ціною релізних гілок, і на жодній схемі моделі її не видно.
Що робить короткі гілки можливими
Команди рідко обирають довгі гілки навмисно. Вони опиняються з ними, бо щось робить раннє злиття неможливим, а винною призначають модель. Справжньою причиною зазвичай є одна з трьох речей.
Затримка рев’ю і розмір зміни
Якщо pull request чекає на рев’юера півтора дня, ніхто не відкриває маленьких: вартість одного оберту фіксована, тож раціонально запхати в кожен більше. Від цього рев’ю стають більшими, а отже повільнішими, а отже пакувати стає ще вигідніше. Петля сама себе підсилює, і це найпоширеніша причина, чому команді не вдається скоротити життя гілки.
Виправлення непоказні: заявлене очікування щодо часу відповіді на рев’ю, виміряне в годинах; розмір, за якого рев’юер має право попросити поділити; і парна чи ансамблева робота для змін, які інакше були б завеликими для рев’ю взагалі. Зверніть увагу: trunk-based не скасовує рев’ю — він його переміщує: або в парну роботу в реальному часі, або в рев’ю, достатньо швидке, щоб процес не вигинався навколо нього.
Великі зміни без великих гілок
Звична заперечна теза проти коротких гілок — великий рефакторинг: заміна платіжного провайдера, зміна ORM, перебудова модуля. Branch by abstraction — техніка-відповідь: ввести інтерфейс перед тим, що замінюють, перевести на нього викликів по одному злиттю, збудувати за ним нову реалізацію, перемкнути, потім видалити стару. Кожен крок — мала, безпечна, окремо злитна зміна, і кодова база придатна до релізу на кожному з них.
Merge, rebase чи squash
Ця суперечка з’їдає більше енергії команди, ніж заслуговує, тож коротко. Merge-коміт зберігає рівно те, що сталося, включно з тим, що дві лінії роботи існували паралельно; на активному репозиторії з короткими гілками це дає історію точну й важку для читання. Rebase переграє ваші коміти поверх поточного транка й дає лінійну історію — ціною переписування комітів, що нормально на власній гілці й шкідливо на спільній. Squash згортає гілку в один коміт, тож історія транка читається як одна зміна на одиницю роботи, а проміжні кроки зникають.
Жоден із трьох варіантів помітно не впливає на результати поставки; оберіть один, запишіть і припиніть обговорення. Що справді важить — правило, з яким погоджуються без суперечок: ніколи не переписуйте історію гілки, на якій хтось інший уже збудував свою роботу. Оце завдає реальної шкоди і, на відміну від естетичного питання, не є справою смаку.
Як це виявляється в реальній поставці
Стратегія гілкування — це місце, де командний процес зустрічається з інженерною практикою, і вона безжально оголює прогалини в останній. Команда не перейде на короткі гілки, якщо її тести йдуть сорок хвилин і нестабільні: ніхто не зливатиме шість разів на день у сигнал, якому не довіряє. Модель гілкування зазвичай є симптомом; причина зазвичай у тестах.
Де вона вироджується
- Фіче-гілка, відкрита місяць, — злиття стає окремим проєктом.
- GitFlow, узятий для вебзастосунку з однією живою версією, додає церемонію, що нікому не служить.
- Гілка на кожного розробника перетворює інтеграцію на періодичні перемовини.
- Хотфікс, застосований до production-гілки й не влитий назад, повертається багом.
- Короткі гілки без прапорців — недороблене або зливають зламаним, або тримають осторонь.
- Переписування історії спільної гілки ламає всіх, хто збудував на ній роботу.
Коли це застосовувати
Застосовуйте, коли
- Обирайте trunk-based, коли в production рівно одна версія, а тести швидкі й надійні.
- Обирайте GitHub Flow як розумний стандарт для продуктової команди, що рев’юить кожну зміну.
- Обирайте GitLab Flow, коли середовища чи невелика кількість версій мають відстежуватися гілками.
- Обирайте GitFlow, коли кілька випущених версій треба підтримувати й патчити паралельно.
- Поєднуйте короткі гілки з прапорцями, щоб недороблене можна було безпечно злити.
Уникайте, коли
- Переходити на trunk-based, доки тести повільні чи нестабільні, — спершу виправте це.
- Брати GitFlow тому, що він звичний, а не тому, що ви випускаєте версії.
- Додавати типи гілок, щоб розв’язати проблему рев’ю чи власності, — це виправлення процесу, а не git.
- Підтримувати більше випущених версій, ніж витягує реальна робота з беквпортів.
- Міняти модель, не змінюючи того, що робило стару болісною.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.