Для чего нужен git flow
Кратко о git-flow
Git-flow — наиболее популярная методология разработки проектов с использованием git.
Зачем нам вообще нужны какие-то методологии для работы с git?
Дело в том, что сам git не привязывает нас к какому-либо определённому способу разработки, и каждый разработчик, в теории, может работать с контролем версий так, как он хочет. Чтобы в таких условиях не погрузить наш репозиторий в хаос, нам нужно придумать и донести до всех разработчиков некий единый стандарт для работы с контролем версий в проекте.
Git-flow даёт нам готовый стандарт проверенный временем и уже известный многим разработчикам.
В то же время, нужно понимать, что методология git-flow не является единственно верной и на 100% универсальной. В Вашем проекте может существовать собственный подход к работе с git. Однако, если вы работаете или собираетесь работать с git в команде, то стоит знать о том, что такое git-flow и в чём его особенности.
И так, что же нам стоит знать о git-flow?
Суть ветвления в git-flow
Всего в git-flow существует 5 типов веток, каждый из которых несёт определённую функциональную нагрузку.
Ветка develop
Ветка существует на протяжении всего процесса разработки. В данную ветку попадает стабильный код новых фич и багфиксов.
Тривиальные фичи, разработка которых умещается в один полноценный коммит, обычно идут прямо в эту ветку. Но те фичи, для реализации которых нужно уже несколько коммитов, выделяются в отдельные ветки feature-*.
Ветки feature-*
Временные ветки, которые создаются для каждой нетривиальной фичи.
Каждая ветка feature отделяется от develop и мержится обратно в него. После завершения работы над фичей и финального мержа в develop, ветка удаляется. При мерже ветки в develop не должен использоваться fast-forward (флаг –no-ff).
Имя ветки должно соответствовать имени разрабатываемой фичи, например “feature-gamecenter-integration”. В некоторых проектах префикс “feature-” опускается (тогда любая ветка без префикса — это ветка feature).
Ветка master
Ветка, куда поступают самые стабильные изменения, которые идут в релиз. Существует на протяжении всего процесса разработки.
В ветку master мержатся только изменения из веток release и hotfix. На каждый такой мерж создаётся тег с именем версии. Полный запрет использования fast-forward при мерже в ветку (флаг –no-ff).
По сути, в самой ветке не должно быть никаких коммитов, кроме коммитов мержей, каждый из которых должен быть отмечен тегом версии.
Ветки release-*
Временные ветки, создаваемые для подготовки новой версии к релизу. В эти ветки попадают правки багов и настройки перед релизом.
Ветка выходит из develop и может мержится в develop по ходу подготовки версии. Как только работа над версией заканчивается, происходит финальный мерж ветки в master и develop, после чего ветка удаляется, а коммиту мержа в master присваивается тег новой версии.
Имя ветки должно соответствовать выпускаемой версии, например “release-1.4”.
Ветки hotfix-*
Временные ветки hotfix-* создаются для правки критических проблем в релизной версии.
Ветка отходит от master и по завершению правок багов мержится обратно. Сама ветка после этого удаляется, а коммиту мержа в master присваивается тег новой версии.
Именем ветки обычно является новая версия с учётом версии фикса, например “hotfix-1.4.1” (первый хотфикс версии 1.4).
Подробнее про ветвление в git-flow можно узнать из оригинальной статьи автора методологии или из её перевода на русский язык.
Инстументы с поддержкой git-flow
По сути нам нет необходимости в каких-то особенных инструментах для поддержания процессов разработки, все действия могут быть выполнены из практически любой графической оболочки над git, либо из командной строки.
Однако, есть удобное расширение для git, которое позволяет немного ускорить ежедневную работу по данной методологиии за счёт уменьшения количества вводимых команд в консоли и работы непосредственно на уровне абстракций git-flow.
Так же, git-flow поддерживается из коробки некоторыми популярными графическими оболочками такими как SourceTree и SmartGit.
Как в случае консольного расширения, так и в случае графических клиентов, мы работаем с более понятными командами вроде “Start Feature” и “Finish Feature”, что позволяет проще смотреть на процесс разработки.
Git-flow и непрерывная интеграция
При разработке с использованием git-flow, одновременно существует две стабильные ветки, которые можно использовать для сборки билдов или выкладки кода на сервер: это ветки master и develop.
Сборки из ветки master можно собирать сразу по поступлении новых изменений. Любые новые правки в этой ветке — это стабильный production-код, который можно выкладывать на сервер (в случае разработки веб-ресурса) либо собирать в релизный бинарник.
Версии собранные из ветки master должны в обязательном порядке подвергаться всем существующим в проекте автоматизированным тестам.
Из ветки develop можно собирать ночные сборки (для тестирования) либо, по мере разработки, можно выкладывать код из этой ветки на тестовый сервер (в случае разработки веб-ресурса).
На версиях собранных из ветки develop следует прогонять unit-тесты.
Когда не стоит применять git-flow
Во первых, git-flow достаточно сложная методология, расчитанная на большие проекты. Если проект относительно небольшой и над ним работает команда всего из 3-4 человек, то применение git-flow может только усложнить процесс разработки.
Во вторых, git-flow в чистом виде применим только в тех случаях, когда в процессе разработки присутствует такое понятие как “релиз”. Если изменения публикуются в продакшн по мере разработки, то смысла применять git-flow тоже нет.
В обоих случаях, можно либо взять git-flow, отказавшись от некоторых типов веток (master, release, hotfix), либо выбрать другую методологию.
Рабочий процесс Gitflow Workflow
Git-flow — это устаревшая версия рабочего процесса Git, в свое время ставшая принципиально новой стратегией управления ветками в Git. Популярность Git-flow стала снижаться под влиянием магистральных рабочих процессов, которые на сегодня считаются предпочтительными для современных схем непрерывной разработки ПО и применения DevOps. Кроме того, Git-flow не слишком удобно применять в процессах CI/CD. В этой публикации приводится описание Git-flow для истории.
Что собой представляет Git-flow?
Git-flow — альтернативная модель ветвления Git, в которой используются функциональные ветки и несколько основных веток. Эта модель была впервые опубликована и популяризована Винсентом Дриссеном на сайте nvie. По сравнению с моделью магистральной разработки, в Git-flow используется больше веток, каждая из которых существует дольше, а коммиты обычно крупнее. В соответствии с этой моделью разработчики создают функциональную ветку и откладывают ее слияние с главной магистральной веткой до завершения работы над функцией. Такие долгосрочные функциональные ветки требуют тесного взаимодействия разработчиков при слиянии и создают повышенный риск отклонения от магистральной ветки. В них также могут присутствовать конфликтующие обновления.
Git-flow можно использовать для проектов, в которых запланирован цикл релизов и реализуется характерная для DevOps методика непрерывной поставки. В этом рабочем процессе используются понятия и команды, которые были предложены в рамках рабочего процесса с функциональными ветками. Однако Git-flow привносит новые специфические роли для разных веток и определяет характер и частоту взаимодействия между ними. Помимо функциональных веток в рамках этого рабочего процесса используются отдельные ветки для подготовки, поддержки и регистрации релизов. При этом вы по-прежнему можете пользоваться преимуществами рабочего процесса с функциональными ветками, такими как запросы pull, изолированные эксперименты и эффективное командное взаимодействие.
Начало работы
Порядок действий
Ветка разработки и главная ветка
В этом рабочем процессе для регистрации истории проекта вместо одной ветки main используются две ветки. В главной ветке main хранится официальная история релиза, а ветка разработки develop предназначена для объединения всех функций. Кроме того, для удобства рекомендуется присваивать всем коммитам в ветке main номер версии.
При использовании библиотеки расширений git-flow, для создания ветки develop можно выполнить команду git flow init в существующем репозитории:
Функциональные ветки (feature)
Обратите внимание, что комбинация веток feature с веткой develop фактически представляет собой рабочий процесс с функциональными ветками. Но рабочий процесс Gitflow на этом не заканчивается.
Создание функциональной ветки
Без использования расширений git-flow:
С использованием расширений git-flow:
Продолжайте работу с Git как обычно.
Окончание работы с функциональной веткой
Без использования расширений git-flow:
С использованием расширений git-flow:
Ветки выпуска (release)
Благодаря тому, что для подготовки выпусков используется специальная ветка, одна команда может дорабатывать текущий выпуск, в то время как другая команда продолжает работу над функциями для следующего. Это также позволяет разграничить этапы разработки (например, можно без труда посвятить неделю подготовке к версии 4.0 и действительно увидеть это в структуре репозитория).
Без использования расширений git-flow:
При использовании расширений git-flow:
Для завершения работы в ветке release используйте следующие команды:
Без использования расширений git-flow:
Или при использовании расширений git-flow:
Ветки исправления (hotfix)
Без использования расширений git-flow:
При использовании расширений git-flow:
По завершении работы с веткой hotfix ее сливают с main и develop (как и в случае с веткой release ).
Пример
Далее показан полный цикл работы с функциональной веткой (предполагается, что у нас есть репозиторий с веткой main ).
Резюме
В этой статье мы рассмотрели модель работы Gitflow. Gitflow — лишь одна из многих методологий работы с Git, доступных вам и вашей команде.
Ключевые идеи, которые нужно запомнить о Gitflow:
Последовательность действий при работе по модели Gitflow:
Готовы изучить Git?
Ознакомьтесь с этим интерактивным обучающим руководством.
GitHub Flow
Увидев в очередной раз базворд GitFlow я психанул и решил перевести описание более простой и менее проблемной схемы работы с ветками под названием GitHub Flow. Именно её имеет смысл использовать по умолчанию, переходя к какой-то другой лишь в случае непреодолимых обстоятельств.
Создайте ветвь
Пока вы работаете над одним проектом, у вас может быть куча различных реализуемых параллельно улучшений. Некоторые из них готовы к работе, а другие — нет. Ветвление позволяет вам управлять этим рабочим процессом.
Ветвление — это основное понятие в git. Весь GitHub Flow основан именно на нем и согласно ему есть только одно правило: всё, что находится в стволе — гарантированно стабильно и готово к деплою в любой момент.
Фиксируйте изменения
Создав ветвь, начинайте вносить в неё изменения. Добавляя, редактируя или удаляя файлы, не забывайте делать новые фиксации (commits) в ветви. Последовательность фиксаций образует в конечном счёте прозрачную историю работы над вашей задачей, по которой остальные смогут понять что вы делали и почему.
У каждой фиксации есть связанное сообщение, являющееся объяснением, почему было сделано то или иное изменение. Также каждая фиксация считается отдельной единицей изменения. Это позволяет откатить изменения, если обнаружилась ошибка, или если вы решите пойти в другом направлении.
Внятное описание фиксации очень важно, так как позволяет остальным разработчикам сразу понять ваши намерения и оценить насколько внесённые изменения им соответствуют. А значит обратная связь от них придёт быстрее и окажется полезней.
Вливайте изменения из ствола в свою ветвь как можно чаще, чтобы она всегда оставалась актуальной и готовой к обратному слиянию. Разрешение возможных конфликтов слияния — право и обязанность разработчика ветви, так как именно он лучше всего знает зафиксированные в ней изменения.
Откройте запрос на слияние
Вы можете открыть запрос на слияние в любой момент процесса разработки:
Используя систему @упоминаний GitHub в сообщении запроса на слияние, вы можете запросить обратную связь от конкретных людей или целых команд, будь то сосед по офису или кто-то в десяти часовых поясах от вас.
Запросы на слияние полезны не только в рамках одного репозитория, но и как инструмент переноса кода между форками. Просто создайте запрос на слияние ветви из одного репозитория в ветвь из другого и действуйте дальше.
Проверьте и обсудите код
После открытия запроса на слияние команда рассматривает изменения, задавая вопросы и оставляя комментарии. Возможно стиль кодирования не соответствует принятому соглашению. Возможно отсутствуют модульные тесты. А возможно все выглядит хорошо и не вызывает нареканий. Запросы предназначены фокусировки обсуждения именно на предлагаемых изменениях и группировки вместе с ними.
Конечно вы можете продолжать пополнять ветку обновлениями в свете возникшего обсуждения. Если вам указывают, что вы забыли что-то сделать или в коде есть ошибка, вы можете исправить это в своей ветке и протолкнуть (push) на сервер. GitHub покажет ваши новые фиксации и любую дополнительную обратную связь на них всё в том же унифицированном представлении запроса на слияние.
В комментариях к запросу на слияние можно использовать markdown размету, что позволяет вставлять изображения и смайлики, использовать предварительно отформатированные текстовые блоки и другое облегченное форматирование.
Проверьте в бою
Вливайте
При слиянии в стволе создаётся фиксация со всеми изменениями из ветки. Как и любые другие фиксации, она доступна для поиска и «перемещения во времени».
А если частые релизы невозможны?
Если вы не практикуете непрерывную поставку (Continous Delivery), то вам может быть сложно доводить до ствола каждую ветвь по отдельности. В этом случае просто создавайте интеграционный ветви, куда вливайте лишь те ветви, что считаете готовыми. Если изменения одной из ветвей вызовут проблемы, то интеграционную ветвь всегда можно будет пересобрать заново, но уже не включая проблемную. Это позволит вам не срывать график релизов, даже если какие-либо из планируемых задач оказались не до конца готовы к запланированной дате.
В чём отличие от GitFlow?
В GitFlow у вас есть дополнительная ветвь develop куда сливаются все разрабатываемые в текущий момент ветви. develop необходимо «стабилизировать» перед релизом, что часто приводит либо к переносу релиза, либо «релизу с замечаниями».
В чём отличие от GitLab Flow?
Пожалуйста, перестаньте рекомендовать Git Flow
Прим. перев.: Новая статья с критикой полюбившейся многим Git Flow получила столь заметное внимание, что даже оригинальный автор модели обновил публикацию 10-летней давности, актуализировав свой взгляд на её применение сегодня. Публикуем перевод как самой критики, так и официальной реакции.
Git-flow — это методология ветвления и слияния, сильно популяризированная заметкой 2010 года под названием «A Successful Git branching model» (была переведена на хабре как «Удачная модель ветвления для Git» — прим. перев.).
За последние десять лет бесчисленное множество команд пали жертвой этого громкого названия и оказались — не побоюсь этого слова — откровенно облапошены. В своей заметке автор утверждает, что они успешно внедрили эту модель в проекты, но умышленно не раскрывает подробности проектов, которые привели к этой «успешности».
И это главная ошибка тех, кто верит данной публикации. Общеизвестен факт, что не все стратегии работают во всех ситуациях, со всеми людьми, во всех контекстах. И я утверждаю, что та же логика применима и к этой модели ветвления.
На этом можно заканчивать, так? Ну, не совсем. Наверняка некоторые из вас скептически отнеслись к моей цепочке рассуждений, поэтому давайте копнем поглубже и попытаемся понять, почему модель ветвления Git-flow должна поджариться на медленном огне.
Git-flow изначально сложна и запутана
Модель Git-flow сложна даже в том случае, если на минуту забыть о микросервисах и непрерывной доставке (continuous delivery, CD). Посмотрите-ка на эту схему и рискните сказать, что она интуитивно понятна:
(источник)
Итак, мы имеем ветви функциональностей (feature), ветви релизов, master, develop, ветви исправлений (hotfix) и теги git. За всеми этими элементами необходимо следить, держать их в уме, учитывать в процессе сборки и выпуска.
Кроме того, нужно постоянно заострять внимание на том, что это за ветка и для чего она предназначена. Ментальная модель, которая требуется для реализации этого подхода, несет в себе высокую когнитивную нагрузку. Я пользуюсь git’ом уже 10 лет, но до сих пор не уверен, что смогу удержать в уме все нюансы происходящего.
Git-flow нарушает правило «короткоживущих» ветвей
В git’е число merge-конфликтов в ветке растет пропорционально числу людей, делающих коммиты в эту ветку. В случае Git-flow это число растет еще быстрее, потому что есть три других ветки (с разной продолжительностью жизни), которые сливаются в develop: ветви функциональностей, релизов и исправлений. Таким образом, потенциальное количество merge-конфликтов теперь минимум в три раза выше.
Я не склонен утверждать, что переживания по поводу merge-конфликтов являются веской причиной отказаться от стратегии ветвления вроде Git-flow, однако потенциальную сложность, связанную с появлением всех этих ветвей, невозможно игнорировать. Такой подход подошел бы для организации с низкой частотой коммитов, но для любой динамично развивающейся компании или стартапа он не пригоден.
С Git-flow придется забыть о rebase’ах
Признаю, что перебазирование — это многогранный вопрос, однако он важен для целей моего повествования. Сторонникам Git-flow придется отказаться от перебазирования: ведь оно происходит вместе со слиянием, в результате которого две ветви объединяются. А учитывая проблемы Git-flow с наглядностью, вам будет необходим способ визуально отслеживать ветви. Чтобы этим не заниматься, придется навсегда забыть о rebase.
Git-flow сильно усложняет непрерывную поставку
Continuous delivery — это практика, при которой разработчики выпускают обновления непосредственно в production (на самом деле, путем слияний с мастером) в автоматическом режиме. А теперь посмотрите на бардак, который творится в Git-flow, и объясните мне, как вы собираетесь проводить непрерывную доставку всего этого?
Вся модель ветвления основана на предсказуемом, долгосрочном цикле релиза новых версий, а не на выпуске нового кода каждые несколько минут или часов. Реализовать это слишком сложно, не говоря уже о принятой в CD практике накатывать исправления «на месте», в то время как Git-flow рассматривает исправления как отдельную сущность, которую необходимо бережно хранить, контролировать ее, держа отдельно от остальной работы.
В Git-flow невозможно работать с несколькими репозиториями
С появлением микросервисов начала набирать популярность и идея микрорепозиториев («Они ортогональны друг другу», — кричит мне суфлер). В ней отдельные команды контролируют свои репозитории и рабочие процессы, а также следят за тем, кто публикует код в их репозитории и как функционируют их workflows.
Вы когда-нибудь пробовали воспользоваться сложной моделью ветвления вроде Git-flow в условиях совместной работы нескольких команд? Получилось ли у вас добиться согласованности их действий? Сомневаюсь. Очень скоро система превращается в манифест различных ревизий разных репозиториев, и единственные, кто знают, где все лежит — это люди, которые пишут YAML-файлы для обновления манифестов. Если не соблюдать должную осторожность, то вопрос «Что у нас в production?» становится экзистенциальным.
Git-flow также не приспособлен для работы с единственным репозиторием
Если микрорепозитории не подходят из-за сложности с координацией релизов, почему бы не реализовать единый глобальный процесс ветвления, который все микросервисные команды будут использовать для релизов?
Увы, он просуществует всего несколько секунд — ровно столько, сколько требуется команде, чтобы сказать: «Это необходимо выпустить прямо сейчас» (хотя остальные команды вовсе не готовы к выпуску своих продуктов). В случае, когда команды работают независимо друг от друга, микросервисы также развертываются независимо, невозможно привязать рабочий процесс к централизованной модели ветвления, организованной в монорепе.
Кому подходит (и не подходит) Git-flow?
Если ваша компания придерживается месячного или квартального цикла выпуска ПО, а команда параллельно работает над несколькими релизами, то Git-flow может стать неплохим выбором. Для стартапа, сайта или веб-приложения со множеством релизов каждый день Git-flow не подходит. Если команда разработчиков невелика (менее 10 человек), то Git-flow вносит в ее работу слишком много церемоний и лишних движений.
С другой стороны, если команда насчитывает 20+ человек, работающих над параллельными релизами, то Gitflow обеспечивает достаточную структурированность, помогающую избежать путаницы.
Окей, моей команде Git-flow не подходит. Что нам использовать?
Я не могу ответить на этот вопрос. Каждая модель ветвления подходит для соответствующих команд, культур и условий. Сторонникам CD подходит модель, максимально упрощающая процесс. Кто-то обожает разработку на основе trunk’ов (trunk-based development) и переключатели функциональности (feature flags). Однако эти подходы до чертиков пугают меня сложностью тестирования.
Основная идея в том, чтобы подробно обсудить эту проблему со своей командой. Задайте ей следующие вопросы:
В заключение хочу сказать, что изначально намеревался использовать в названии устойчивое выражение «considered harmful», столь привычное для публикаций подобного рода. Однако поиск в google показал, что кто-то уже использовал его для своей статьи о вредности Gitflow. Рекомендую ее почитать.
Бонус. Ответ nvie (Vincent Driessen)
На следующий день после этой публикации автор оригинала «A Successful Git branching model» (Vincent Driessen), на которую ссылается George Stocker, разместил ответ:
Эта модель родилась в 2010 году — более 10 лет назад — практически сразу после того, как появился Git. За эти 10 лет Git-flow (модель ветвления, описанная в оригинальной статье) приобрела настолько высокую популярность у разработчиков, что ее начали рассматривать как своего рода стандарт — но, к сожалению, и как некую догму или панацею.
За эти 10 лет сам Git покорил весь мир, а наиболее распространенный тип программного обеспечения, разрабатываемого с помощью Git, все сильнее смещается в сторону веб-приложений — по крайней мере, таковы мои наблюдения. Как правило, веб-приложения разрабатываются в рамках подхода CD, не откатываются и не требуют поддержки нескольких одновременно запущенных версий ПО.
Это вовсе не тот класс ПО, который я имел в виду, когда писал свою статью десять лет назад. Командам, занимающимся непрерывной доставкой ПО, я бы рекомендовал использовать гораздо более простой рабочий процесс (вроде GitHub flow) вместо того, чтобы пытаться интегрировать Git-flow в свою работу.
В свою очередь, Git-flow может подойти командам, которые разрабатывают ПО с жестким версионированием или занимаются поддержкой нескольких версий приложения параллельно (Git-flow неплохо себя зарекомендовал на этом поприще за последние 10 лет). В этом случае рекомендую обратиться к оригинальной статье.
В заключение хочу напомнить вам, что панацеи не существует. Учитывайте свои условия, контекст и думайте своей головой!