Пошук уроків, статей та іншого контенту
Застосовуйте модель Git Flow із гілками feature, develop, release та hotfix для керування релізним циклом.
Git Flow — модель організації гілок Git для проєктів із запланованими релізами. Вона розділяє:
стабільний код, який уже випущено;
код наступної версії;
окремі функціональні зміни;
підготовку релізу;
термінові виправлення продакшену.
Основні гілки моделі:
main — код, що відповідає випущеним версіям;
develop — інтеграційна гілка наступного релізу;
feature/* — розробка окремих функцій;
release/* — стабілізація конкретного релізу;
hotfix/* — термінові виправлення вже випущеної версії.
У деяких проєктах замість main використовують назву master. Важливо заздалегідь узгодити назву в команді.
mainУ main потрапляє лише код, готовий до релізу. Кожен реліз зазвичай позначають Git-тегом, наприклад:
v2.4.0
v2.4.1Гілка main повинна залишатися стабільною. Нові функції безпосередньо в неї не додають.
developdevelop містить зміни, які планують включити до наступного релізу. Саме до цієї гілки зливають завершені функціональні гілки.
На відміну від main, develop може містити ще не випущені функції, але після завершення роботи над релізом його стан має бути готовим для створення release-гілки.
feature/*Функціональна гілка призначена для однієї функції або логічної зміни. Її створюють від develop:
feature/user-profile
feature/payment-validation
feature/search-filtersПісля завершення роботи гілку зливають назад у develop. Функціональні гілки не створюють від main, якщо зміна не є терміновим виправленням.
release/*Гілка релізу потрібна, коли функціонально склад наступної версії вже визначено й команда переходить до стабілізації.
Її створюють від develop, наприклад:
release/2.4.0У release зазвичай виконують такі дії:
виправляють помилки;
оновлюють номер версії;
змінюють документацію релізу;
перевіряють складання та тести;
не додають нові великі функції.
Після завершення release зливають і в main, і назад у develop. Це важливо, щоб виправлення, зроблені під час стабілізації, не загубилися в наступній розробці.
hotfix/*hotfix використовують для термінової помилки у випущеній версії. Таку гілку створюють від main, а не від develop:
hotfix/2.4.1Після виправлення її зливають у main, створюють новий тег і також зливають у develop.
Спрощено цикл має такий вигляд:
main
└── release/2.4.0 ──> main
└── develop
develop
├── feature/login ──┘
├── feature/search ─┘
└── release/2.4.0
main
└── hotfix/2.4.1 ──> main
└── developПослідовність:
Створити feature від develop.
Реалізувати та протестувати функцію.
Злити feature у develop.
Коли склад релізу завершено, створити release від develop.
Стабілізувати реліз і злити його в main та develop.
Створити тег у main.
Для критичної помилки створити hotfix від main.
Злити hotfix у main та develop, після чого створити новий тег.
Якщо репозиторій уже створено, можна створити develop від поточного main:
git switch main
git pull origin main
git switch -c develop
git push -u origin developКоманда -u встановлює зв’язок локальної гілки з віддаленою. Після цього достатньо виконувати git push і git pull без додаткової назви гілки.
Перед початком роботи корисно перевірити стан репозиторію:
git status
git branch --allПрипустімо, потрібно додати пошук товарів.
git switch develop
git pull origin develop
# Створюємо функціональну гілку від актуального develop
git switch -c feature/product-search
# Після внесення змін перевіряємо їх
git status
git add src/search.js
git commit -m "Add product search"
# Публікуємо гілку для спільної роботи або code review
git push -u origin feature/product-searchПісля перевірки змін гілку зливають у develop. Це можна зробити через платформу для code review або локально:
git switch develop
git pull origin develop
# Зливаємо завершену функцію зі збереженням окремого merge-коміту
git merge --no-ff feature/product-search
git push origin develop
# Видаляємо локальну гілку після успішного злиття
git branch -d feature/product-search
# Видаляємо віддалену гілку, якщо вона більше не потрібна
git push origin --delete feature/product-searchПрапорець --no-ff створює окремий merge-коміт навіть тоді, коли Git міг би виконати fast-forward. У Git Flow це допомагає зберігати межі функціональної роботи в історії.
Коли команда вирішила, що develop містить усі функції для версії 2.4.0, створюють релізну гілку:
git switch develop
git pull origin develop
# Створюємо гілку для стабілізації релізу
git switch -c release/2.4.0
# Публікуємо її, щоб команда могла тестувати реліз
git push -u origin release/2.4.0У цій гілці можна виправляти знайдені помилки:
git add package.json CHANGELOG.md
git commit -m "Prepare release 2.4.0"
git pushЯкщо під час стабілізації потрібен код, якого немає в release, його не варто безконтрольно додавати. Значні нові функції краще повернути до наступного релізного циклу.
Після успішного тестування реліз зливають у main:
git switch main
git pull origin main
# Додаємо зміни релізу до стабільної гілки
git merge --no-ff release/2.4.0
# Позначаємо випущену версію тегом
git tag -a v2.4.0 -m "Release 2.4.0"
git push origin main
git push origin v2.4.0Потім той самий реліз зливають у develop:
git switch develop
git pull origin develop
# Повертаємо релізні виправлення в наступну гілку розробки
git merge --no-ff release/2.4.0
git push origin develop
# Релізна гілка більше не потрібна після завершення релізу
git branch -d release/2.4.0
git push origin --delete release/2.4.0Злиття в develop потрібне навіть тоді, коли Git не показує очевидних відмінностей. Так команда явно фіксує, що реліз завершено, а всі зміни залишаються доступними для наступного циклу.
Припустімо, у версії 2.4.0 виявлено критичну помилку. Спочатку потрібно перейти на main і отримати останній стан:
git switch main
git pull origin main
# Створюємо hotfix від випущеного коду
git switch -c hotfix/2.4.1Після виправлення:
git add src/payment.js
git commit -m "Fix payment calculation"
git push -u origin hotfix/2.4.1Завершення hotfix відбувається подібно до релізу:
git switch main
git pull origin main
# Додаємо термінове виправлення до стабільної гілки
git merge --no-ff hotfix/2.4.1
# Збільшуємо patch-версію
git tag -a v2.4.1 -m "Release 2.4.1"
git push origin main
git push origin v2.4.1Потім виправлення потрібно перенести в develop:
git switch develop
git pull origin develop
# Не втрачаємо hotfix у майбутньому релізі
git merge --no-ff hotfix/2.4.1
git push origin develop
git branch -d hotfix/2.4.1
git push origin --delete hotfix/2.4.1Якщо develop уже суттєво змінив код, під час злиття можуть виникнути конфлікти. Їх потрібно розв’язати, перевірити тести й лише потім завершити merge-коміт.
Git Flow визначає призначення гілок, але не диктує єдиний спосіб code review. Команда може встановити правила:
прямий push до main заборонено;
прямий push до develop дозволено лише в окремих випадках або також заборонено;
кожна feature потрапляє до develop через pull request;
release зливається в main після успішного тестування;
злиття в main дозволене лише з release або hotfix;
кожен реліз має анотований тег.
Для важливих гілок корисно налаштувати захист:
обов’язкове code review;
успішне проходження автоматичних перевірок;
заборона force push;
обов’язкове оновлення гілки перед злиттям.
У наведеному прикладі використано версію 2.4.0:
2 — major-версія;
4 — minor-версія;
0 — patch-версія.
У межах Git Flow важливо, щоб назва release- або hotfix-гілки та Git-тега узгоджувалися:
release/2.4.0 → v2.4.0
hotfix/2.4.1 → v2.4.1Тег створюють у коміті main, який відповідає випущеній версії. Це дозволяє повернутися до точного стану коду, що був опублікований.
Переглянути наявні теги можна так:
git tag --listПерейти до стану конкретного релізу:
git switch --detach v2.4.0Такий режим призначений для перегляду або перевірки. Для нової розробки краще працювати в окремій гілці.
Нижче наведено скорочений сценарій від функції до релізу:
# Оновлюємо інтеграційну гілку
git switch develop
git pull origin develop
# Створюємо гілку функції
git switch -c feature/notifications
# Виконуємо зміни та фіксуємо їх
git add .
git commit -m "Add notifications"
git push -u origin feature/notifications
# Після code review зливаємо функцію в develop
git switch develop
git pull origin develop
git merge --no-ff feature/notifications
git push origin develop
# Створюємо релізну гілку
git switch -c release/2.5.0
git push -u origin release/2.5.0
# Після тестування випускаємо версію
git switch main
git pull origin main
git merge --no-ff release/2.5.0
git tag -a v2.5.0 -m "Release 2.5.0"
git push origin main
git push origin v2.5.0
# Синхронізуємо develop із завершеним релізом
git switch develop
git merge --no-ff release/2.5.0
git push origin developКоманди злиття потрібно виконувати лише після перевірки, що робоче дерево чисте:
git statusНезбережені локальні зміни можуть ускладнити перемикання гілок або спричинити конфлікти.
feature від mainЯкщо функціональну гілку створити від main, вона не міститиме поточних змін із develop. У результаті під час злиття можуть виникнути зайві конфлікти або неповний набір функцій.
Правильно:
git switch develop
git switch -c feature/examplehotfix від developdevelop може містити незавершені функції, тому виправлення, створене від нього, не обов’язково можна безпечно випустити.
Правильно:
git switch main
git switch -c hotfix/2.5.1release лише в mainЯкщо не злити release назад у develop, виправлення версії можуть бути відсутні в наступному релізі.
Після злиття в main потрібно виконати також:
git switch develop
git merge --no-ff release/2.5.0releaseРелізна гілка призначена для стабілізації, а не для продовження звичайної розробки. Нові функції збільшують ризик і змінюють уже погоджений склад релізу.
Без тегу складно точно визначити, який коміт відповідав випущеній версії. Створюйте тег після злиття релізу або hotfix у main.
developПеред створенням нової гілки потрібно отримати актуальний стан віддаленого репозиторію:
git switch develop
git pull origin developІнакше нова гілка може бути створена на основі старого коміту.
Перед локальним видаленням переконайтеся, що зміни справді потрапили до потрібної гілки:
git log --oneline --graph --decorate --allGit Flow добре підходить, якщо:
релізи мають чіткі версії;
між релізами потрібна окрема стабілізація;
над продуктом працює кілька команд;
у продакшен потрібно іноді випускати термінові виправлення;
функції можуть розроблятися паралельно.
Модель створює більше гілок і процесів, тому для невеликого проєкту з безперервним розгортанням вона може бути надто складною. Вибір моделі потрібно узгодити з частотою релізів, процесом тестування та правилами команди.
main містить випущені та стабільні версії.
develop об’єднує функції для наступного релізу.
feature/* створюють від develop і після завершення зливають назад.
release/* використовують для стабілізації погодженого релізу.
release зливають і в main, і в develop.
hotfix/* створюють від main для термінових виправлень.
hotfix також зливають у main і develop.
Випущені версії позначають тегами, наприклад v2.4.0.
Перед створенням гілки потрібно оновлювати її базову гілку.
Захист main, code review та автоматичні перевірки допомагають підтримувати передбачуваний релізний процес.