Коли реліз складається з однієї маленької задачі, окрема release branch може бути зайвою.
Але коли кілька задач змінюють один функціональний блок, я більше не сприймаю їх як незалежні merge у development.
Для мене release branch у такій ситуації стає інтеграційною межею. Саме там пов’язані зміни вперше повинні працювати разом як один майбутній реліз.
Цей підхід особливо добре показав себе в великих релізах, де поруч змінювалися backend, frontend, permissions, realtime-поведінка, аналітика та тести.
Проблема не в самому merge, а в частково зібраному релізі
Task A | vdevelopment Task B | vdevelopment Task C | vdevelopment Якщо Task A уже в development, а Task B ще на перевірці, система може опинитися в проміжному стані, який ніхто не планував як окремий реліз.
Може бути новий API без нового frontend, новий permission без UI, новий listener без повного набору подій або нова аналітика без усіх джерел даних.
Кожна задача окремо може бути правильною, але реліз ще не є цілісним.
У release branch пов’язані задачі збираються до того, як вважаються релізом
main | vrelease/feature-area | +<-- feature/task-a | +<-- feature/task-b | +<-- feature/task-c | +-- integration fixes | vstabilized release |Release branch я створюю від стабільної бази - актуального main.
Далі пов’язані feature branches інтегруються в release branch, де проходять спільну перевірку. Саме тут я виправляю інтеграційні помилки, які неможливо було побачити в ізольованих задачах.
Після об'єднання змін, стабілізації та проходження перевірок увесь реліз одним merge request вливається в development.
Таким чином development отримує завершений функціональний блок, а не послідовність окремих задач.
Пов’язані задачі часто мають приховані залежності
Завдання для бекенду:новий стан сповіщень Завдання для фронтенду:новий індикатор непрочитаних повідомлень Завдання для системи реального часу:трансляція змін стану Завдання щодо прав доступу:керування доступом Завдання для аналітики:відстеження прочитань і реакцій Окремо:У великих релізах найцікавіші помилки часто знаходяться не всередині конкретної задачі, а на стику кількох задач.
Наприклад, backend уже повертає новий стан, але frontend оновлює його тільки після reload. Realtime event приходить, але permission не дозволяє підписатися на channel. Аналітика готова, але один сценарій не створює потрібний event.
Release branch дає окреме місце саме для такого класу проблем.
Release branch має починатися зі стабільної бази
git fetch origin git switch \ -c release/feature-area \ origin/mainДля мене важливо, щоб release branch не успадковувала випадковий локальний стан іншої feature branch.
Вона повинна починатися від зрозумілої стабільної бази. Тоді весь diff релізу можна читати як одну майбутню зміну системи.
Перед інтеграцією feature branches я також перевіряю їхню базу та склад комітів. Це важливо, щоб випадково не перенести в реліз сторонні зміни з development, які не належать до нього.
Release branch не скасовує feature branches
Я все одно залишаю окрему feature branch для кожної логічної задачі.
Це зберігає невеликий review scope, окремі тести й зрозумілу історію змін.
Різниця лише в точці інтеграції: feature branch вливається в release branch, а не безпосередньо в development. Лише після спільної стабілізації весь реліз переходить у development як одна інтеграційна одиниця.
Повний набір тестів я запускаю тоді, коли реліз уже зібраний
Кожна задача повинна мати свої targeted tests під час розробки.
Але дорогий повний набір тестів має найбільшу цінність тоді, коли release branch уже містить усі заплановані зміни й основні фікси.
Інакше можна витратити багато часу на повний прогін після кожного merge, хоча наступна задача ще змінить той самий код.
Для кожного завдання: цільові тестиlintстатичний аналіз змінених ділянок коду На зібраній release branch: повний набір тестівповний статичний аналізlintінтеграційні перевіркизбіркаперевірка конфігурації та міграцій Фікси я роблю всередині release branch
Після злиття кількох задач часто з’являються дрібні виправлення, які не належать одній feature branch повністю.
Наприклад, треба узгодити назву поля між backend і frontend або поправити спільний layout після підключення нового state.
Такі виправлення входять до складу release branch, тому що виникають саме під час інтеграції релізу.
Залежно від складності я можу внести їх окремими комітами або через невеликі fix branches із перевіркою змін. Після виправлень повторно запускаю необхідні тести.
Я не використовую development як тимчасове місце для незавершеної інтеграції
Для мене development - це спільна гілка, до якої мають потрапляти вже зібрані та перевірені функціональні блоки.
Я не використовую її для поступового складання великого релізу, коли його окремі частини ще не можуть повноцінно працювати разом.
Якщо функціональність ще не завершена як єдиний реліз, я залишаю її в release branch до завершення інтеграції.
Такий підхід дозволяє зберегти development зрозумілішим і водночас не блокувати паралельну роботу над кількома пов’язаними задачами.
Release branch дає один diff для фінальної перевірки
git diff \ origin/main...release/feature-areaЦе дуже корисно перед фінальним merge.
Окремі merge requests пояснюють конкретні задачі, а фінальний diff release branch показує зміни релізу відносно спільної точки історії з main.
Саме на цьому рівні легше помітити випадковий файл, зайвий налагоджувальний код, конфігураційну зміну або залежність між задачами.
Окремо я перевіряю майбутнє злиття з development. Оскільки ця гілка може містити інші зміни, успішні тести на release branch ще не гарантують, що результат інтеграції працюватиме без проблем.
Якщо одна задача проблемна, реліз ще можна перебудувати до злиття в development
Release branch залишає простір для рішення: виправити задачу, замінити її реалізацію або, якщо це безпечно, відкласти її з релізу.
Поки реліз ще не злитий у development, такі рішення залишаються всередині release branch. Якщо склад релізу змінюється, я повторно перевіряю залежності між задачами та запускаю необхідні тести.
Це простіше, ніж спочатку влити кілька залежних змін у development, а потім намагатися відкотити одну з них без впливу на інші.
Я визначаю готовність на рівні релізу, а не останньої задачі
Остання feature branch може бути повністю готовою, але це ще не означає, що готовий реліз.
Для мене готовність релізу включає спільні тести, перевірку конфліктів поведінки, збірку, конфігурацію, міграції, права доступу, готовність необхідних runtime-процесів і сценарій розгортання.
Тільки після цього release branch перестає бути місцем активної інтеграції та стає готовим кандидатом для merge request у development.
Release branch потрібна не для кожної зміни
Я не хочу перетворювати цей підхід на правило для кожного bugfix.
Якщо зміна маленька, незалежна й може бути безпечно випущена сама, окрема release branch лише додасть зайві кроки.
Вона стає корисною тоді, коли кілька задач разом утворюють одну продуктову або технічну одиницю і мають спільний момент готовності.
Коли я обираю release branch як інтеграційну межу
Реліз складається з кількох пов’язаних задач.
Пов’язані задачі не повинні потрапляти в development незалежно одна від одної.
Є integration bugs, які можна побачити лише після збирання всіх частин.
Повний набір тестів дорогий і має сенс на зібраному релізі.
Потрібен один final diff від стабільної бази.
Ми хочемо мати можливість стабілізувати або змінити склад релізу до final merge.
Готовність визначається для всього релізу, а не для останньої задачі.
Для великого релізу integration boundary важливіша за окремі merge
Release branch не робить окремі feature branches менш важливими. Вона додає ще один рівень, якого бракує великим змінам: рівень інтеграції релізу.
Окремі задачі можна розробляти, тестувати й перевіряти незалежно. Але перед злиттям у development вони повинні довести, що працюють разом як один реліз.
Для мене це і є головна роль release branch: не зберігати код між merge, а дати цілому релізу власну межу готовності.
Feature branch відповідає на питання «Чи готова ця задача?». Release branch відповідає на інше питання: «Чи готові всі ці задачі працювати разом як один реліз?». У моєму процесі release branch створюється від main, збирає пов’язані задачі, проходить стабілізацію й одним merge request інтегрується в development. Подальше просування змін до production - окремий етап із власними перевірками та рішенням про готовність до випуску.



