Git Flow
Git flow — это популярная методология ветвления и слияния, которая описывает несколько веток для разработки, релизов и взаимодействия между ними.
Схематично Git flow выглядит так:

Основные принципы
Основные идеи Git Flow состоят в том, что существует несколько типов веток:
- главные ( master и develop ) — существуют всё время.
- вспомогательные ( feature , release и hotfix ) — используются для распараллеливания разработки между членами команды. Всегда имеют ограниченный срок жизни — каждая из них в итоге удаляется.
Подробнее о ветках:
- master . Дефолтная ветка знакомая каждому, кто работал с гитом. Она всегда содержит стабильный код. Код, попадая в нее, образует очередной релиз.
- develop . Создаётся параллельно ветке master и является главной ветвью для разработки. Хранящийся в ней код в любой момент времени должен содержать самые последние изданные изменения, необходимые для следующего релиза. Когда исходный код в этой ветке достигает стабильного состояния и готов к релизу, все изменения должны быть определённым способом (при помощи ветки release ) влиты в главную ветвь ( master ) и помечены тегом с номером релиза.
- feature . Ответвляются от ветки develop . Используются для разработки новых функций, которые должны появиться в текущем или будущем релизах, т.е. заранее неизвестно в какой из релизов они попадут. Когда работа в ветке завершена, она вливается обратно в develop и удаляется. При неудавшемся эксперименте ветка удаляется без вливания куда-либо.
- release . Ответвляются от ветки develop , имена должны присваиваться по типу release-* . Используются для подготовки к выпуску новых версий продукта, т.е. здесь осуществляются небольшие исправления, подготавливается информация для релиза (номер версии, дата сборки и т.д.). Когда вся эта работа завершена, ветка вливается в develop и master .
- hotfix . Ответвляются от ветки master , имена должны присваиваться по типу hotfix-* . Данные ветки порождаются необходимостью немедленно исправить какие-либо ошибки или неправильную работу функционала в текущем релизе. Когда баг исправлен, изменения надо влить обратно в master , а также в ветвь develop , чтобы гарантировать, что это исправление окажется и в следующем релизе.
Плюсы и минусы
Плюсы:
- Git Flow используется многими распределенными командами, в т.ч. и open source команды, которые имеют разные уровни квалификации. Сопровождающие проекта могут проводить код ревью и утверждать каждую строку кода в релизы.
- Git Flow хорошо подходит для “традиционной модели релизов”, где релизы делаются раз в месяц или раз в пару недель.
- Git Flow также хорошо работает при работе с установленным продуктом или несколькими версиями в производстве.
Минусы:
- Git Flow может замедлять работу, когда приходится ревьювить большие пулл реквесты, когда вы пытаетесь выполнить итерацию быстро.
- Релизы сложно делать чаще, чем раз в неделю.
- Большие функции могут потратить дни на мерж и резолв конфликтов и форсировать несколько циклов тестирования.
- История проекта в гите имеет кучу merge commits и затрудняет просмотр реальной работы.
- Может быть проблематичным в CI/CD сценариях.
git-flow (AVH Edition)
Существует специальный инструмент, который облегчает работу с методологией Git Flow — gitflow-avh. Включает в себя коллекцию расширений для git, которая помогает избежать многих повторяющихся операций.
Основные команды: 
- start — создаёт ветку (feature, release или hotfix).
- finish — сливает ветку в develop и/или master .
- publish — публикация ветки на удалённом сервере.
- pull — получение ветки, которую опубликовал другой пользователь.
Полезные ссылки
Branching стратегии в Git — статья о нескольких методологиях ветвления (Git flow, Github flow, GitLab flow, Trunk Based Development).
Удачная модель ветвления для Git — плюсы Git Flow.
Пожалуйста, перестаньте рекомендовать Git Flow — минусы Git Flow.
Шпаргалка по git-flow-avh — информация о том как начать использовать gitflow-avh.
Branching стратегии в Git

Прежде чем поговорить о лучших практиках, давайте разберемся с худшими практиками и анти-паттернами при работе с любой бранч стратегией.
Branching & merging анти-паттерны:
- Merge Paranoia – когда девелоперы боятся мержить код, из-за последствий которые могут возникнуть (мерж конфликты) поэтому накапливается негативный эффект отложенной интеграции.
- Merge Mania – когда разработчики больше времени тратят на объединение изменений, чем на разработку.
- Big Bang Merge – В ветки не подмерживаются изменения, как следствие в конце происходит один гигантский мерж в конце.
- Never-Ending Merge – непрерывный мержинг, так как всегда есть что мержить.
- Wrong Way Merge – объединение более поздней бранчи с более ранней версией.
- Branch Mania – создание большого количества веток без видимой на то причины.
- Cascading Branches – создание веток без мержа их в mainline в конце разработки.
- Mysterious Branches – создание ветки без причины.
- Temporary Branches – создание ветки с изменяющейся причиной ее существования: ветка становится "permanent temporary workspac'ом".
- Volatile Branches – старт ветки в нестабильном состоянии или перенос нестабильных изменений в другие ветки.
- Development Freeze – остановка всей разработки для создания веток, объединения или создания релизов.
- Berlin Wall – использование веток для разделения людей в команде, вместо разделения на таски/фичи, над которыми они работают.
Git Flow (Feature Based Development)
Схематично Git Flow можно описать так:

Git Flow — одна из первых крупных стратегий ветвления, которая завоевала популярность. Git Flow описывает несколько веток для разработки, релизов и взаимодействия между ними.
Главные ветки:

По сути модель перекочевала с других существующих моделей. Репозиторий содержит 2 главные ветки:
- master
- develop
master — дефолтная ветка знакомая каждому, кто работал с гитом. Параллельно в этой концепции существует еще одна ветка develop .
Master в этой концепции всегда содержит стабильный код, а develop бранча существует для того чтобы от нее бранчеваться и сливать туда уже готовые фичи для последующего мержа в master . Как следствие master выступает релизной (иногда) и stable бранчей в этой концепции.
- Feature branches
- Release branches
- Hotfix branches
Feature branches
- Могут бранчеватся от develop
- Должны вмержится в develop
- Naming convention: любые названия кроме master , develop , release-* , или hotfix-*
Release branches
- Могут бранчеватся от develop
- Должны вмержится в develop и master
- Naming convention: release-*
Помните, до того как вмержить код в релиз ветку, необходимо добавить ей тег с версией релиза (например "0.9 hotfix")
Hotfix branches
- Могут бранчеватся от master
- Должны вмержится в develop и master
- Naming convention: hotfix-*
Плюсы и минусы Git Flow:
Плюсы:
- Git Flow используется многими распределенными командами, в тч и open source команды, которые имеют разные уровни квалификации. Сопровождающие проекта могут проводить код ревью и утверждать каждую строку кода в релизы.
- Git Flow хорошо подходит для "традиционной модели релизов", где релизы делаются раз в месяц или раз в пару недель.
- Git Flow также хорошо работает при работе с установленным продуктом или несколькими версиями в производстве.
Минусы:
- Git Flow может замедлять работу, когда приходится ревьювить большие пулл реквесты, когда вы пытаетесь выполнить итерацию быстро.
- Релизы сложно делать чаще, чем раз в неделю.
- Большие функции могут потратить дни на мерж и резолв конфликтов и форсировать несколько циклов тестирования.
- История проекта в гите имеет кучу merge commits и затрудняет просмотр реальной работы.
- Может быть проблематичным в CI/CD сценариях.
GitHub Flow

Он выглядит почти так же как и Git Flow, но фиксированная ветка всего одна — master ; всё остальное принадлежит тематическим ветвям. Тематические ветви, в свою очередь, создаются в форках — клонированных копиях репозитория. То есть центральный репозиторий тематических веток не содержит. В том числе и после слияния, так как метки веток при этом снимаются и их головы становятся анонимными.
GitLab Flow
Как и в GitHub Flow, фиксированная ветка всего одна — master, всё остальное принадлежит тематическим ветвям. Однако, если в том случае релизы размещались в коммитах master-a, то здесь для каждого релиза создаётся своя, отдельная ветка. Причём никакого мержа этих веток с parent'ом не производится. Если ветка отбранчевалась, значит она будет жить своей жизнью, получая исправления ошибок в виде отдельных коммитов (возможно, портированных из head/master с учётом накопившейся разницы в функционале между ветками).
Environment branches в GitLab flow

Release branches в GitLab flow

Trunk Based Development (TBD)
На официальном сайте эта концепция отображается такой схемой:

Лично для меня, когда я стал изучать эту концепцию эта схема показалась совсем не понятной и не раскрывала суть этой концепции. Давайте же разберемся подробнее простым языком в чем суть Trunk Based Development.
Что такое Trunk Based Development (TBD) ?
TBD прозволяет бизнесу тестировать бизнес-гипотезы "As soon as possible". Тк позволяет очень быстрыми итерациями релизить код на продакшн.
В Trunk Based Development можно выделить следующие особенности:
- Ветки живут максимум 2 дня
- Feature Flags
- Branch By Abstraction
- Continuous Code Review (это концепция из экстримального программирования которая говорит о том, что код который попадает на ревью, должен ревьювится как можно быстрее)
- master всегда готов к деплою, даже если в нем есть не готовые фичи
Feature Flags
Feature Flags — это концепция в которой у нас есть файл конфигурации, где прописано какая из фич включена/выключена и в коде существует проверка которая позволяет пропускать какую-то логику, например
Приемущества использования Feature Flags
- Можем мержить и деплоить код, который еще не готов
- A/B тесты
- Шаринг кода между недоработанными фичами, за счет мержа всего кода в master
Branch By Abstraction
Trunk Based Development предлагает вместо создание ветки для фич, создавать ветку на изменение одной абстракции.
Представим, что у нас есть объект Car , у которой есть абстракция “передние колоса” и “задние колеса”, которые мы хотим заменить на другой тип колес. В случае с feature branch, мы бы разработали реализацию нового типа колес в 1 бранче, с Branch By Abstraction все немного сложнее.
Рассмотрим рисунок и шаги которые нам помогут раскрыть порядок действий при TBD подходе

- Создаем ветку, оборачиваем переднее колесо в абстракцию, отправляем Pull Request, мержим
- Создаем ветку, описываем новый тип передних колес и добавляем feature flag переключения типов колес, отправляем Pull Request, мержим
- Создаем ветку, оборачиваем заднее колесо в абстракцию, отправляем Pull Request, мержим
- Создаем ветку, описываем новый тип задних колес и добавляем feature flag переключения типов колес, отправляем Pull Request, мержим
- Включили в проде новый тип колес, убедились, что все ок
- Удаляем старые колеса отдельными Pull Request`ами
И что нам это дало?
- Частые интеграции! Мы уже пришли ранее к тому что нужно часто интегрировать маленькие кусочки кода(CI), теперь при таком подходе можно делать "микрокусочки".
- Постепенное изменение/рефакторинг кода. Вместо переделки всего разом, меняем постепенно, шарим изменения до того как закончим большую задачу.
- Возможность переключения на другие фичи. В случае, если нужно переключиться на другую задачу, мы можем смежить последнее изменения и вернуться к доработке потом.
Continuous Code Review
Ревьювим чужие pull requests, сразу после того как отправили свой. Из-за этого что пулл реквесты маленькие(изменение одной абстракции), их ревью занимает не более чем пару минут, Если от создания пулл реквеста до аппрува прошло 10 минут, то это приемлемый результат, если больше 1 часа, то это считается очень плохим результатом.
Модель ветвления Gitflow
В предыдущей статье мы начали говорить о моделях ветвления при работе с Git и рассмотрели модель Feature Branch Workflow. В данной статье мы рассмотрим еще одну популярную модель ветвления – Gitflow.
Данная статья является переводом англоязычной статьи из обучающих материалов Atlassian.
Модель ветвления Gitflow была впервые опубликована и стала популярной, благодаря статье Vincent Driessen. Она предполагает выстраивание строгой модели ветвления вокруг релиза проекта, которая дает надежную схему управления крупными проектами.
Gitflow отлично подходит для проектов, которые имеют спланированный цикл релиза. Эта модель не предполагает дополнительных понятий, кроме тех, что описаны для модели Feature Branch Workflow. Вместо этого она приписывает особые роли разным веткам и определяет, как и когда они должны взаимодействовать. Кроме feature-веток в ней используются отдельные ветки для подготовки, поддержки и записи релиза. Конечно, также необходимо эффективно использовать все преимущества Feature Branch Workflow: пул-реквесты, изоляция для изменений и эффективное сотрудничество внутри команды.
Gitflow использует собственный набор инструментов git-flow, который легко интегрируется с Git, добавляя новые команды Git.
Начало работы
Gitflow является методологией работы с Git. Это значит, она определяет, какие ветки нужно создать и как производить их слияние. Далее мы рассмотрим назначение веток. Набор инструментов git-flow нужно установить отдельно. Процесс его установки довольно понятный. Пакеты команд git-flow доступны во многих операционных системах. Для системы OSX можно выполнить brew install git-flow . Для Windows необходимо скачать и установить git-flow. После установки git-flow необходимо выполнить команду git flow init . Git-flow является оберткой для Git. Команда git flow init является расширением стандартной команды git init и ничего не меняет в вашем репозитории, кроме того, что создает ветки.
Как это работает

Ветки master и develop
Вместо использования одной ветки master, в этой модели используется две ветки для записи истории проекта. В ветке master хранится официальная история релиза, а ветка develop служит в качестве интеграционной ветки для новых функций. Также, удобно тегировать все коммиты в ветке master номером версии.
Первым шагом является создание ветки develop от ветки master. Проще всего это сделать одному разработчику, локально создав пустую ветку и отправив ее в центральный репозиторий:
В этой ветке будет находиться вся история проекта, в то время как master содержит частичную историю. Остальные разработчики теперь должны клонировать центральный репозиторий и создать отслеживающую ветку для ветки develop .
При использовании библиотеки расширений git-flow, для создания ветки develop можно выполнить git flow init в существующем репозитории:
Ветки для функций (feature branches)
Каждая новая функциональность должна разрабатываться в отдельной ветке, которую можно отправлять в центральный репозиторий для создания резервной копии/для совместной работы команды. Ветки функций создаются не на основе master , a на основе develop . Когда работа над новой функциональностью завершена, она вливается назад в develop. Новый код не должен отправляться напрямую в master.

Обратите внимание, что ветки функций объединяются с веткой develop как в модели Feature Branch Workflow. Но на этом работа по схеме Gitflow не заканчивается.
Создание ветки функции
Без использования расширений git-flow:
При использовании git-flow:
Далее, продолжайте работу c Git как обычно.
Окончание работы с веткой
По окончании разработки новой функциональности следующим шагом следует объединить ветку feature_branch c develop. Используйте команды:
Без использования расширений git-flow:
При использовании git-flow:
Ветки релиза

Когда в ветку develop уже слито достаточно нового кода для релиза (или подходит установленная дата предрелиза), от ветки develop создается ветка release . Создание данной ветки означает начало следующего цикла релиза, в ходе которой новая функциональность уже не добавляется, а производится только отладка багов, создание документации и решение других задач, связанных с релизом. Когда все готово, ветка release сливается в master , и ей присваивается тег с версией. Кроме этого, она должна быть также слита обратно в ветку develop , в которой с момента создания ветки релиза могли добавляться изменения с момента создания ветки релиза.
Использование отдельной ветки для подготовки релиза позволяет одной команде дорабатывать текущий релиз пока другая команда уже работает над функциональностью для следующего релиза. Это также позволяет разграничить этапы разработки (например, легко сказать: «На этой неделе мы готовимся к версии 4.0» и фактически увидеть это в структуре репозитория).
Создание веток релиза – это еще одна простая операция ветвления. Как и ветки функций, ветки релизов основаны на ветке develop . Новая ветка release может быть создана с использованием следующих команд:
Без использования расширений git-flow:
При использовании git-flow:
Когда релиз готов к отправке, он сливается в master и develop , а ветка релиза удаляется. Важно влить ее обратно в develop , поскольку в ветку release могут быть добавлены критические обновления, и они должны быть доступны для новых функций. Если ваша команда делает акцент на проверку кода, этот момент идеален для пул-реквеста.
Для завершения работы на ветке релиза, используйте следующие команды:
Без использования расширений git-flow:
Или при использовании git-flow:
Ветки hotfix

Ветки hotfix используются для быстрого внесения исправлений в рабочую версию кода. Ветки hotfix очень похожи на ветки release и feature , за исключением того, что они созданы от master , а не от develop . Это единственная ветка, которая должна быть создана непосредственно от master . Как только исправление завершено, ветка hotfix должна быть объединена как с master , так и с develop (или с веткой текущего релиза), а master должен быть помечен обновленным номером версии.
Наличие специальной ветки для исправления ошибок позволяет команде решать проблемы, не прерывая остальную часть рабочего процесса и не ожидая следующего цикла подготовки к релизу. Можно говорить о ветках hotfix как об особых ветках relese , которые работают напрямую с master . Ветка hotfix может быть создана с помощью следующих методов:
Без использования расширений git-flow:
Или при использовании git-flow:
Как и в работе с веткой release, ветка hotfix объединяется как с master , так и с develop .
Пример
Пример команд, демонстрирующий полный цикл работы с веткой функции, выглядит следующим образом. Предположим, что у нас есть репозиторий с веткой master .
Помимо ветки функции и release , приведем пример создания ветки hotfix :
Заключение
В этой статье мы рассмотрели модель работы Gitflow. Gitflow – это одна из многих моделей ветвления Git, которую можете использовать вы и ваша команда.
Ключевые идеи, которые нужно запомнить о Gitflow:
- Данная модель отлично подходит для организации рабочего процесса на основе релизов.
- Gitflow предлагает создание отдельной ветки для исправлений ошибок в продуктовой среде.
Последовательность работы при использовании модели Gitflow:
- Из master создается ветка develop .
- Из develop создаются ветки feature .
- Когда разработка новой функциональности завершена, она объединяется с веткой develop .
- Из develop создается ветка release .
- Когда ветка релиза готова, она объединяется с develop и master .
- Если в master обнаружена проблема, из нее создается ветка hotfix .
- Как только исправление на ветке hotfix завершено, она объединяется с develop и master .
Если статья вам понравилась и была для вас полезной, поделитесь ей с друзьями.
GitLab Flow VS Git flow VS GitHub flow
Это перевод достаточно важной статьи про GitLab Flow, альтернативе Git flow и GitHub flow. Статья была написана в 2014, так что скриншоты успели устареть. Тем не менее сама статья более чем актуальна:
Ветвление и слияние веток в git устроено гораздо проще, чем в более ранних системах контроля версий, таких как SVN. Поэтому есть много способов организации командной работы над кодом, и большинство из них достаточно хороши. По крайней мере, они дают много преимуществ по сравнению с тем, что было до git. Но сам по себе git — не серебряная пуля, и во многих командах организация рабочего процесса с git имеет ряд проблем:
- Не описан точным образом весь рабочий процесс,
- Вносится ненужная сложность,
- Нет связи с трекером задач (issue tracker).
Мы хотим представить вам GitLab flow — чётко определённый набор практик, решающий эти проблемы. Он объединяет в одну систему:
- Практику разработки, управляемой функциональностью (feature driven development),
- Использование feature-веток (feature branches),
- Трекер задач.
Эта статья описывает все аспекты GitLab flow, включая работу с ветками, интеграцию с задачами, непрерывную интеграцию и развёртывание. Её цель — помочь новым командам перейти на git и сразу внедрить простые, прозрачные и эффективные правила работы с ним.

В большинстве систем контроля версий, чтобы поделиться кодом с коллегами, нужно сделать одно действие — коммит в репозиторий. В git то же самое происходит в три этапа:
- Добавить изменения из рабочей области проекта в индекс (область подготовленных файлов, staging area);
- Сделать коммит на основе индекса;
- Запушить коммит в удалённый репозиторий.
Освоение этих действий — первый шаг в изучении git. Следом идет работа с ветками.

Если не устанавливать никаких правил работы с ветками, в репозитории начинает расти энтропия:
- Появляется много долгоживущих веток,
- Вносимые изменения оказываются размазанными по разным веткам,
- Непонятно, откуда начинать разработку новой фичи или откуда разворачивать код на production.
Для решения этих проблем обычно внедряется некая стандартная модель работы, например git flow или GitHub flow. Мы считаем, что у всех этих моделей есть потенциал для улучшения, поэтому мы разработали GitLab flow.
Git flow и его ограничения

Модель рабочего процесса Git flow появилась одной из первых и стала довольно широко известной. Она предполагает наличие основной ветки master , ветки для накопленных изменений develop , а также отдельных веток для фич, релизов и хотфиксов. Разрабатываемые изменения мержатся в develop , оттуда в релизные ветки, и в итоге попадают в master . Git flow достаточно подробно и четко определяет рабочий процесс, но его сложность порождает две проблемы.
Во-первых, разработчики должны использовать ветку develop , а не master , потому что последняя зарезервирована под релизный код. Это противоречит привычной практике называть master основную ветку, от которой ответвляются прочие ветки, и в которую мержится результат. Нередко разработчики по ошибке мержат какие-то изменения только в master , забывая про develop . А большинство графических интерфейсов к git по умолчанию считают основной веткой именно master , поэтому в них приходится каждый раз что-то переключать или настраивать.
Во-вторых, лишняя сложность появляется из-за веток релизов и хотфиксов. Большинство команд, особенно небольших, может легко обойтись без них. Сегодня большинство организаций придерживается практики непрерывной доставки (continuous delivery), которая предполагает, что код из основной ветки можно развёртывать на продакшен (production, то, что предоставляется пользователям).
Следовательно, можно исключить ветки релизов и хотфиксов и всю лишнюю работу, которая для них требуется. Пример такой лишней работы — обратный мерж релизных веток в master . Для решения этой проблемы есть специальные инструменты, но они тоже требуют изучения документации и только добавляют сложности.
GitHub flow – более простой вариант

В противовес сложной модели git flow был разработана модель GitHub flow. В ней есть только master и feature-ветки. Это упрощение привело к успешному внедрению GitHub flow множеством компаний. Компания Atlassian предложила похожую стратегию. Но, в отличие от GitHub, они предпочитают делать ребейз (rebase), а не мерж веток в master .
Мерж всех изменений в master и частое развёртывание позволяют не писать код «в стол», а сразу выпускать изменения. Это соответствует идеям бережливого (lean) производства и непрерывной доставки. Но множество вопросов остаются без ответа: когда именно нужно развёртывать и в каких окружениях, как выпускать релизы, как связать всё это с трекером задач. GitLab flow отвечает на все эти вопросы.
GitLab flow: ветка production

GitHub flow строится на предположении, что вы можете развернуть ваш код на продакшен в любой момент, сразу после мержа feature-ветки в master . Это верно для SaaS-приложений, но неверно в множестве других случаев. Бывает, что вы не можете влиять на точное время релиза. Например, вы выпускаете приложение под iOS и каждое обновление должно пройти валидацию в AppStore. Другой пример — когда релизить можно в строго определённое время (например, с 10 до 16 в будние дни, когда все сотрудники находятся на рабочем месте), но замержить ветку в master можно в любое время.
Для управления выпуском кода в продакшен GitLab flow предлагает использовать специальную ветку production . Настройте автоматическое развёртывание кода из этой ветки при каждом изменении в ней. Теперь для релиза достаточно сделать мерж из ветки master в production . Состояние ветки даст вам точную информацию о том, какая версия кода сейчас выпущена, а приблизительное время выпуска можно будет определить по времени создания мерж-коммита. Если вам нужна абсолютная точность, можно в процессе развёртывания создавать новый тег с timestamp’ом в описании.
GitLab flow: ветки для нескольких сред

Может быть полезно иметь отдельную среду (environment), в которую происходит развёртывание из ветки master . В этом единственном случае название среды может отличаться от названия ветки.
Предположим, что у вас есть несколько сред: стейджинг (staging), пре-продакшен (pre-production) и продакшен (production). Код из master автоматически развёртывается на стейджинг. Как только вы готовы развернуть его на пре-продакшен, вы создаете мерж-реквест из master в pre-production . Соответственно, мерж из pre-production в production означает окончательный релиз. Такой процесс, когда все коммиты проходят через ветки в строго определенном порядке, гарантирует, что изменения прошли тестирование во всех средах.
Если вам нужно быстро «протащить» хотфикс на продакшен, то можно реализовать его в обычной feature-ветке, а потом открыть мерж-реквест в master , не удаляя ветку. Теперь, если код в master проходит тесты и жизнеспособен (правильно настроенная непрерывная доставка должна гарантировать это), вы можете замержить ветку хотфикса последовательно в pre-production и production . Если же изменения требуют дополнительного тестирования, то вместо немедленного мержа нужно открыть мерж-реквесты в те же ветки. В «экстремальном» случае отдельная среда может создаваться для каждой ветки. Так делается, например, в Teatro.
GitLab flow: релизные ветки

Ветки релизов понадобятся вам только если вы выпускаете ПО для внешних клиентов. В таком случае каждая минорная версия будет храниться в отдельной ветке ( 2.3-stable , 2.4-stable и т.п.).
Стабильные (stable) ветки должны создаваться от ветки master . Их нужно создавать как можно позже, чтобы минимизировать добавление хотфиксов в несколько веток. После того, как релизная ветка создана, в неё можно включать только исправления серьёзных багов. Следуйте правилу «upstream first»: всегда, когда это возможно, сначала делайте мерж исправлений в master , и только оттуда — cherry-pick в релизную ветку. Благодаря этому правилу вы не забудете сделать cherry-pick исправлений в master и не встретите тот же самый баг в следующем релизе. Правило «upstream first» применяется в том числе в Google и Red Hat. Каждый раз, когда в релизную ветку добавляется исправление бага, нужно повысить третье число в номере версии (по правилам семантического версионирования). Обозначьте эту версию новым тегом в git. В некоторых проектах используется ветка stable , которая всегда указывает на тот же коммит, что и последний релиз. Ветка production (или master в правилах git flow) в таком случае не нужна.
GitLab flow: мерж/пулл-реквесты

Мерж-реквест или пулл-реквест создаётся в системе управления git-репозиториями. Это запрос на мерж одной ветки в другую, подобно задаче, назначаемый на какого-либо исполнителя. GitHub и Bitbucket используют термин «пулл-реквевст», потому что первое необходимое действие — сделать пулл предлагаемой ветки. GitLab и Gitorious используют термин «мерж-реквест», потому что заключительное действие — собственно, мерж ветки. Далее в этой статье мы будем называть это мерж-реквестом.
Если вы работаете над веткой больше, чем пару часов, имеет смысл поделиться промежуточным результатом с коллегами через мерж-реквест. Не назначайте его на кого-либо, а просто упомяните (командой /cc @имя ) ваших коллег в описании реквеста или в комментарии — они получат уведомление. Это будет означать, что реквест не готов к мержу, но по нему уже можно давать обратную связь. Вы можете явным образом обозначить, что работа над реквестом не завершена. Для этого начните заголовок реквеста с [WIP] или WIP: , то есть «Work in progress». Такой мерж-реквест даже нельзя будет замержить через интерфейс GitLab (хотя по-прежнему можно вручную через git).
Интерфейс GitLab позволяет оставлять комментарии как к реквесту в целом, так и к конкретным строкам кода. Таким образом, мерж-реквест уже включает в себя инструментарий для ревью кода, и какие-то дополнительные инструменты вам не понадобятся. По результатам ревью кто угодно может внести правки следующим коммитом в ту же ветку (обычно это делает автор реквеста). Все последующие коммиты, запушенные в эту же ветку, включаются в мерж-реквест, а дифф обновляется автоматически и корректно работает даже с push -f .
Когда фича готова, и ветку можно мержить, назначьте реквест на того, кто хорошо знает код проекта (и у кого есть права на мерж в master ). Этот человек несёт ответственность за окончательное ревью и принимает решение: замержить результат или закрыть реквест без мержа.
В GitLab есть стандартная практика — «защищать» долгоживущие ветки (такие как master или production ). Защита ветки не позволяет участникам с уровнем доступа «Developer» пушить в неё любые изменения.
Поэтому для мержа в защищённую ветку нужно открывать мерж-реквест, назначаемый на участника с более высоким уровнем доступа.
GitLab flow: интеграция с задачами (issues)

GitLab flow позволяет вам явным образом связывать код и задачи из трекера.
Любые значимые изменения в коде должны сопровождаться задачей, в которой сформулированы требования и смысл изменений. Это помогает оставаться в рамках задачи, а также даёт команде представление о том, чем вы заняты. В GitLab каждое изменение кодовой базы начинается c оформления задачи в трекере. Если предполагаемые изменения хоть сколько-нибудь серьёзны (например, требуют более часа работы), то работу нужно начинать с оформления задачи. Многие команды уже следуют этому правилу, потому что всегда оценивают время выполнения задачи, прежде чем взять её в спринт.
Заголовки задач желательно формулировать так, чтобы они описывали желаемое состояние системы.
Хороший пример: «Как администратор, я хочу иметь возможность удалить пользователя без ошибок».
Плохой пример: «Админ не может удалять пользователей».
Приступая к работе над задачей, создайте новую ветку от ветки master . Её название должно начинаться с номера тикета, например 42-admin-can-remove-users .
Когда вы завершили работу над задачей или хотите получить промежуточную обратную связь, открывайте мерж-реквест. Помните о возможности отправить оповещение ( /cc @имя ) коллегам и отметке WIP: .
В момент, когда вы считаете, что работа завершена, назначьте реквест на ревьюера и уберите WIP: .
Ревьюер может принять (замержить) реквест как через командную строку, так и через кнопку в интерфейсе реквеста. Нажатие на кнопку автоматически создаёт мерж-коммит, описание которого формируется на основе описания реквеста. Мерж-коммит полезен тем, что он сохраняет в истории время и обстоятельства мержа. Поэтому, по умолчанию, коммит создаётся всегда, даже если был возможен «fast-forward merge», когда master просто переключается на последний коммит вашей ветки. В git эта стратегия называется «no fast-forward» и используется с командой git merge —no-ff . GitLab EE и .com предлагают выбор поведения при мерже, подробности далее в статье.
Feature-ветка обычно больше не нужна после мержа, поэтому интерфейс реквеста позволяет удалить её. Предположим, что ветка была замержена, после чего вы обнаружили какие-то недоработки и переоткрыли задачу. Если старая ветка удалена, можно создать новую ветку с тем же именем и продолжить разработку в ней. Как правило, одной задаче соответствует не более одной ветки, но в одной ветке может решаться несколько задач.
Связывание задач и мерж-реквестов

В сообщении коммита, либо в описании мерж-реквеста можно упомянуть задачу по её номеру, используя слово-триггер, например: fixes #14 , closes #67 . При этом GitLab публикует в упомянутой задаче комментарий с обратной ссылкой на коммит или реквест. А в мерж-реквесте появляется список связанных задач. Когда вы замержите код в основную ветку, связанные задачи будут отмечены как выполненные. Обратите внимание: триггеры распознаются только на английском, то есть fixes #14 сработает, а исправляет #14 — нет.
Если вы хотите создать ссылку на задачу, но не закрывать её, напишите просто её номер: «Duck typing is preferred. #12».
Если некоторая задача охватывает несколько репозиториев, лучше всего создать основную задачу в одном репозитории и привязать к ней отдельные задачи в других репозиториях.
Rebase и объединение коммитов

Git позволяет объединить (squash) несколько коммитов в один или поменять их порядок с помощью команды rebase -i . В GitLab EE и .com вы можете сделать это непосредственно перед мержем через веб-интерфейс. Это имеет смысл, если в процессе работы вы сделали несколько небольших коммитов, но хотите чтобы в master попал один, или если хотите выстроить коммиты в логическом порядке.
Помните, что коммиты, которые уже попали в удалённый репозиторий и, тем более, в стабильную ветку, ребейзить нельзя. Причина этого в том, что-нибудь мог оставить ссылку на них или вытащить (cherry-pick) в свою ветку. Ребейз меняет идентификаторы (SHA-1) коммитов, потому что фактически создаёт из них новые коммиты. В результате ваши изменения появляются в истории git с несколькими разными идентификаторами, что приводит к путанице и ошибкам. Ребейз также затрудняет ревью кода, так как теряется информация о том, какие изменения были внесены после ревью. Если объединяются коммиты разных авторов, то информация об авторстве тоже будет потеряна. Это лишает авторов указания на их авторство, а ещё мешает работе git blame (показывает, в каком коммите и кем изменялась каждая строка).
Регулярно делать коммиты и пушить их в удалённый репозиторий — хорошая практика, позволяющая коллегам видеть, над чем вы работаете. Но при таком подходе одна задача размазывается на много коммитов, так что историю разработки становится довольно сложно просматривать. Эти небольшие коммиты можно было бы объединить в один, но это приведёт к потере идентификаторов. Вместо этого можно просматривать историю по мерж-коммитам: они всегда объясняют суть изменения и обозначают момент мержа целой ветки.
Изменения, которые уже попали в master , нельзя стирать из истории и не так просто отменить через git revert . Если все коммиты были объединены в один с помощью rebase , можно применить revert к этому единственному коммиту. Однако мы убеждены, что в объединении коммитов больше вреда, чем пользы. К счастью, git умеет отменять мерж-коммиты. Если вы передумали и хотите вернуть отменённый мерж-коммит, то применяйте revert к коммиту, созданному в результате первого revert . Git всё равно не позволит вам замержить один и тот же коммит дважды.
Чтобы это стало возможным, необходимо сначала создать этот мерж-коммит. Поэтому, если вы мержите вручную, добавляйте опцию —no-ff . Система управления репозиториями сделает это за вас в момент принятия мерж-реквеста.
Не меняйте порядок коммитов с помощью rebase

Git позволяет вам сделать ребейз feature-ветки на master , в результате чего коммиты этой ветки оказываются в истории после коммитов в master . Это позволяет сделать мерж без мерж-коммита и в результате у вас получается простая линейная история. Но здесь действует то же правило, что и с объединением коммитов: не трогайте то, что уже попало в удалённый репозиторий. Мы рекомендуем не ребейзить даже промежуточные результаты вашей работы, отданные на ревью через мерж-реквест.
Использование rebase вынуждает вас многократно разрешать одни и те же конфликты. В некоторых случах это можно сделать командой git rerere (reuse recorded resolutions). Но ещё проще — вовсе не ребейзить и разрешать конфликты всего один раз, при мерже. Чем с меньшим количеством мерж-конфликтов вы сталкиваетесь — тем лучше.
Чтобы избежать лишних конфликтов, нужно не слишком часто мержить master в feature-ветки. Давайте разберём три возможных причины мержа master куда-либо ещё: «подтягивание кода» (leveraging code), мерж-конфликты и долгоживущие ветки.
Если вам нужно «подтянуть» изменения из master в feature-ветку — обычно можно обойтись вытаскиванием (cherry-pick) одного нужного коммита.
Конфликт при мерже feature-ветки обычно разрешается с помощью создания мерж-коммита. Если строки вашего файла могут находиться в произвольном порядке, то можно избежать некоторых конфликтов с помощью настройки gitattributes. Например, в файле .gitattributes репозитория GitLab есть строка CHANGELOG merge=union , и это позволяет мержить список изменений автоматически.
Последняя ситуация, когда необходимо мержить master куда-то ещё — это использование долгоживущих веток, которые периодически нужно обновлять до актуального состояния. Мартин Фаулер в своей статье о feature-ветках рассуждает о практике непрерывной интеграции (continuous integration, CI). Мы в GitLab немного путаем CI с тестированием веток.
Цитируя Фаулера: «Я знаю людей, которые утверждают, что практикуют CI, потому что выполняют сборку каждой ветки и каждого коммита, и даже могут при этом использовать CI-сервер. То, что они делают, называется непрерывной сборкой (continuous building). Это тоже благородное дело, но интеграции-то нет, а значит, нет и «непрерывной интеграции».»
Решение заключается в том, что feature-ветки должны существовать недолго и быстро мержиться. Можно ориентироваться на срок в один рабочий день. Если разработчик держит ветку для реализации задачи более одного дня, подумайте о том, чтобы раздробить задачу на более мелкие части. В качестве альтернативы можно использовать «переключатели фич» (feature toggles).
Для работы с долгоживущими ветками есть две стратегии:
- Стратегия непрерывной интеграции предполагает, что вы мержите master в долгоживущую ветку в начале каждого дня,
чтобы предотвратить более сложные мержи в будущем. - Стратегия «точки синхронизации» (synchronization point strategy) разрешает мержить только строго определённые коммиты,
например отмеченые тегом релизы. Линус Торвальдс рекомендует именно такой способ, потому что код релизных версий лучше изучен.
GitLab EE предлагает возможность делать rebase непосредственно перед принятием мерж-реквеста. Вы можете включить эту возможность в настройках проекта, выбрав Merge Requests Rebase .
Перед принятием мерж-реквеста выберите опцию rebase before merge .
GitLab попытается сделать rebase перед мержем. Если rebase без конфликтов невозможен, будет выполнен обычный мерж.
В заключение хотелось бы сказать следующее: старайтесь делать меньше мерж-коммитов, но не исключайте их вовсе. Ваш код должен быть чистым, но его история должна быть достоверной. Разработка ПО происходит небольшими и не всегда красивыми шагами. То, что они сохранятся в истории кода — нормально. А ребейз делает историю недостоверной, после чего никакие инструменты не покажут вам действительную историю, потому что они не могут узнать идентификаторы коммитов, которые были до ребейза.
Используйте эмодзи в задачах и мерж-реквестах
Общепринятая практика — выражать одобрение или неодобрение с помощью кнопок +1 и -1.
В GitLab вы можете использовать эмодзи, чтобы, например, «дать пять» автору хорошей задачи или мерж-реквеста.
Пуш и удаление веток

Мы рекомендуем регулярно пушить локальные ветки в удалённый репозиторий, даже если код ещё не готов к ревью. Таким образом вы страхуетесь от ситуации, в которой кто-то другой начал работу над той же задачей. Разумеется, более правильный способ — назначить этой задаче исполнителя с помощью трекера задач. Но иногда этот способ даёт сбой, просто потому что никто об этом не вспомнил.
Когда ветка замержена в master , её можно удалить из репозитория. В GitLab и подобных ему системах это можно сделать непосредственно во время мержа. Это гарантирует, что при обзоре веток в системе управления репозиториями, вы увидите только те, над которыми действительно идёт работа. А ещё это освобождает имя и позволяет назвать им новую ветку. Это необходимо, если вы переоткрыли задачу и вам нужна новая ветка и новый мерж-реквест.
Делайте коммиты часто и пишите к ним корректные сообщения

Мы рекомендуем начать коммитить код как можно раньше и делать это регулярно. Каждый раз, когда у вас есть работающий набор из кода и тестов к нему, можно сделать коммит. Преимущество этого способа в том, что если следующий этап работы зайдёт в тупик, вы всегда сможете вернуться к рабочей версии кода. Это кардинально отличается от работы с SVN, где код можно коммитить только тогда, когда он полностью готов. Когда ваша работа завершена, используйте мерж/пулл-реквест, чтобы поделиться ей.
Сообщение коммита должно описывать ваши намерения, а не пересказывать содержимое кода — его и так несложно посмотреть. Важно то, зачем вы сделали этот коммит.
Пример хорошего сообщения: «Скобминировать шаблоны, чтобы разгрузить интерфейс пользователя».
Некоторые слова портят сообщение, потому что ничего конкретного не значат: «поменять», «улучшить», «отрефакторить» и т.п. Слова «чинит», «исправляет» тоже лучше не использовать, только если вы не пишете «fix» (только на английском) в конце сообщения и вместе с номером задачи. Если вы хотите больше подробностей, рекомендуем прочитать отличную статью из блога Tim Pope.
Тестирование перед мержем

В старых моделях рабочего процесса сервер непрерывной интеграции (CI server), как правило, запускал тесты только на ветке master . Поэтому разработчикам приходилось нести ответственность за то, чтобы не сломать master . В GitLab flow разработчики создают свои ветки от master , поэтому её всегда нужно поддерживать «зелёной». Поэтому каждый мерж-реквест нужно тестировать, прежде чем мержить. Инструменты CI, такие как GitLab CI или Travis, умеют показывать результаты сборки (build) непосредственно в мерж-реквесте.
Слабое место этого метода в том, что тестируется ветка, а не результат её мержа. Ошибки могут возникнуть в процессе мержа, поэтому более надёжно тестировать результат. Сложность этого подхода в том, что этот результат меняется каждый раз, когда в master попадают новые коммиты. Повторение тестов каждый раз, когда меняется master , потребует больших вычислительных ресурсов, так что вы гораздо чаще будете ждать, пока пройдут тесты.
Если ветки мержатся быстро и конфликтов при мерже нет, то обычно можно рискнуть и замержить, не тестируя результат. Если конфликты всё-таки есть, то можно замержить master в feature-ветку (т.е. наоборот), после чего ваш сервер CI запустит тесты на полученном коммите. Если feature-ветки живут дольше, чем несколько дней, стоит подумать об уменьшении масштаба ваших фич.
Мерж чужого кода в ваш код

Когда начинаете работу над задачей, всегда создавайте feature-ветку от последнего коммита в master . Только если ваша работа требует изменений из определённой ветки, начните с этой ветки. Если впоследствии вам понадобилось замержить другую ветку, обязательно объясните необходимость этого в сообщении мерж-коммита. Пока вы не запушили вашу ветку в общий репозиторий, можно ребейзить её на master или другую ветку. Не нужно мержить стабильные ветки в свои feature-ветки, если в этом нет строгой необходимости. Линус Торвальдс вообще запрещает мержить стабильные ветки в feature-ветки, за исключением крупных релизов.