(Полное раскрытие: я люблю Gitflow. У меня с ним только одна проблема…)

Вы находитесь в типичном цикле разработки. Мэри только что закончила слияние feature/jetpacks с develop, Тим завершил feature/laser-beams на прошлой неделе, и вы быстро прошли feature/rainbow-launcher.

Это хороший набор функций, которые помогут решить ряд проблем, поднятых нашими клиентами. Ваш руководитель проекта очень доволен. Как только feature/moon-shoes и feature/hot-sauce-fountain попадут в ветку develop, релиз будет готов к выходу!

Но у нас есть одна проблема. Это Кларенс. Он работал над feature/literal-time-travel последние пять месяцев и знаете что? Он готов. Я имею в виду действительно готово. Он видел какое-то дерьмо. Если мы не объединим этого плохого парня с develop и не начнем с feature/therapy-kittens быстро, он уйдет и пойдет работать в магазин разработчиков в соседнем квартале. Знаешь, тот, у которого есть капсулы для сна.

Но мы не можем просто объединить нашу функцию путешествий во времени прямо в develop, прежде чем вырезать ветку релиза. Это слишком сложно, и этот выпуск уже будет таким большим. Лучше включить этот код в следующий выпуск, чтобы у нас было дополнительное время для исправления ошибок. Но что нам делать? Нам еще нужно дождаться наших лунных туфель и острого соуса, прежде чем релиз будет готов. Однако мы также не хотим, чтобы путешествия во времени не попадали в develop, пока мы ждем.

На данный момент у нас есть история Git, которая выглядит примерно так:

(1.23.45) develop
(1.23.46) develop <-- feature/jetpacks
(1.23.47) develop <-- feature/laser-beams
(1.23.48) develop <-- feature/rainbow-launcher

Мэри хочет начать работу над feature/raptors-with-jetpacks, но нам нужно, чтобы наша feature/literal-time-travel ветвь была объединена с develop, прежде чем она разветвляется, чтобы она могла вернуться во времени и найти хищников. Похоже, нам придется сейчас сократить выпуск, а затем объединить feature/literal-time-travel в develop. Затем Мэри может создать свою ветку функции на develop и продолжить свой путь. Лучше сделать это, чем заставлять Мэри вручную объединять ветку путешествий во времени со своей новой ветвью. Мы не хотим, чтобы ей приходилось поддерживать ветку, зависящую от другой ветки, которая заблокирована от слияния с develop.

Без проблем. Мы разрезаем нашу release/1.23.48 ветку, а затем повышаем версию нашей develop ветки до 1.24.01. Теперь мы можем безопасно объединить feature/literal-time-travel в develop, не затрагивая предстоящий выпуск. Когда feature/moon-shoes и feature/hot-sauce-fountain будут готовы, мы объединим их в ветку выпуска, а затем снова объединим ветку выпуска в develop.

Но подождите одну секунду. Наша ветка релиза объявлена ​​на версии 1.23.48. Это правильно в названии! Если мы объединим в него две оставшиеся функции, разве мы не хотим поднять версию в ветке выпуска до 1.23.50? В противном случае 1.23.48 будет иметь раздутое представление о вводимых функциях. К сожалению, Gitflow никогда не предполагал, что мы добавляем дополнительные функции в наши релизные ветки после того, как они будут вырезаны. Он только хочет, чтобы мы добавили в релиз документацию и исправления критических ошибок; изменения, которые не требуют увеличения версии.

Это так важно? Если мы хотим добавить в выпуск больше функций, нужно ли нам увеличить номер версии для каждой из них? Нет, я полагаю, что нет, но это было бы немного глупо. И не в духе Гауда. Мы хотим иметь возможность оглянуться на нашу историю версий и получить точное семантическое представление о том, какая отдельная функция была добавлена ​​в каждую версию.

Хорошо, хорошо. Версии подтолкнем. Что будет хуже? Наши лунные туфли и функции горячего соуса объединены в ветку выпуска, и теперь у нас есть история, которая выглядит следующим образом:

(1.23.48) release/1.23.48
(1.23.49) release/1.23.48 <-- feature/moon-shoes
(1.23.50) release/1.23.48 <-- feature/hot-sauce-fountain

Ха ... это странно. Сейчас наша ветка выпуска находится на версии 1.23.50, но называется она release/1.23.48. Это вроде как неудобно, но мы можем с этим справиться, верно?

Не забывайте, мы также хотим объединить ветку выпуска обратно в разработку, чтобы наши рапторы из реактивного ранца также могли раскачивать лунную обувь и наслаждаться фонтаном горячего соуса:

(1.24.01) develop
(1.24.02) develop <-- release/1.23.48 (new moon-shoes!)
(1.24.03) develop <-- release/1.23.48 (hot sauce fountain)

Хорошо, мы закончили тестирование ветки выпуска и теперь готовы объединить ее в master. Следуем нашей удобной шпаргалке по Gitflow и запускаем git flow release finish. Все идет гладко. Наша ветка master обновляется содержимым из нашей ветки выпуска, наша ветка release/1.23.48 удаляется, и у нас есть новый блестящий тег, который нужно подтолкнуть.

Мы вставляем наш последний тег в github и видим 1.23.48. Ах, орехи.

Gitflow был достаточно любезен, чтобы создать для нас тег в качестве шага на git flow release finish, однако он использовал номер версии из названия ветки выпуска. Не забывайте, Gitflow никогда не предназначался для того, чтобы мы добавляли дополнительные функции в нашу ветку выпуска. После легкого ворчания мы вручную создаем и поднимаем тег версии 1.23.50 и ложимся спать.

Это огромная проблема? Нет, не совсем. Я думаю, что это может быть просто недосмотр в отличной в остальном системе! Gitflow предполагает, что мы развиваемся в пузыре. Предполагается, что каждая функция, которая проверяется и объединяется в develop, готова к переходу в master (и, следовательно, в нашу производственную среду) в любой момент, когда мы разрезаем ветвь выпуска.

По моему опыту, мы часто хотим оставить более сложную функцию на некоторое время в develop, пока мы работаем над выпуском. Или, может быть, мы хотим дать себе время протестировать релиз без произвольного добавления к нему дополнительных функций (кроме тех, которые действительно хотят добавить). Мы можем "заморозить" develop, пока все функции для выпуска не будут объединены, а затем вырезать ветку выпуска. Однако блокировать доступ к develop другим функциям (не из следующего выпуска) - это плохо. Это мешает разработчикам использовать код этих функций для работы над будущими вещами. Они могли просто объединить заблокированную ветвь функции со своей веткой, но теперь их ветка функции также становится заблокированной. Это просто превращается в беспорядок.

Ветка релиза должна быть в состоянии стать де-факто «источником истины» для любого релиза после его вырезания. Дополнительные функции выпуска, которые необходимо включить в выпуск, могут быть объединены в ветку выпуска. А затем ветвь выпуска может быть снова объединена с develop. Capiche?

/ rant