Стратегии ветвления в Git
Что это такое
Стратегия ветвления — общее соглашение команды о смысле веток: сколько они живут, что во что можно сливать, как готовят выпуск. В обсуждении доминируют две именованные стратегии. Первая, trunk-based development, держит main всегда готовым к выпуску, а каждую ветку — короткоживущей, часто на день. Вторая, GitFlow, держит несколько долгоживущих веток — линию develop, ветки выпуска, ветки хотфиксов — и интегрирует их на границах выпусков.
Почему это важно
От стратегии зависит, сколько боли приносит интеграция и как часто она случается. Долгоживущие ветки откладывают встречу двух изменений, поэтому слияние в итоге получается большим, а конфликты — настоящими. Trunk-based development заставляет изменения встречаться каждый день, пока каждое из них мало и понятно. Эта же разница решает, возможна ли вообще непрерывная интеграция. Система CI скажет, что сборка зелёная, только когда собирает нечто близкое к тому, над чем работают люди.
Ключевые идеи
Trunk-based: короткие ветки, один всегда готовый к выпуску main
Работа идёт в ветке, которая живёт часы или дни и часто сливается обратно в ствол. Незавершённое прячут за флагом функции: код уходит в выпуск, а сама функция пока не видна. Взамен вы получаете маленькую поверхность интеграции, сборку, которая всегда отражает реальность, и выпуск, ставший решением, а не проектом.
main ----o----o----o----o----> всегда готов к выпуску
\ / \ /
o o ветки сливаются в течение дня
GitFlow: долгоживущие линии для планового поезда выпусков
Ветка develop собирает работу, ветка выпуска её стабилизирует, а ветки хотфиксов правят бой напрямую. Подходит это продуктам с настоящим ритмом выпусков, несколькими поддерживаемыми версиями в поле или шагом, который приходится стабилизировать вручную. Цена — develop расходится с main надолго: слияния большие, конфликты частые, а CI на develop не скажет, собрался бы бой.
main ----o--------------o-------->
\ /
develop ------o--o--o--o--o
\
release o--o
Стратегия следует за процессом выпуска
Спрашивать надо не о том, какая стратегия лучше, а о том, как выглядят ваши выпуски. Если любой коммит можно развернуть в любой момент, связным остаётся только trunk-based. Если выпуск означает заморозку кандидата, ручной цикл тестирования и отгрузку в назначенную дату, ветка выпуска становится реальной сущностью, и GitFlow моделирует её напрямую. Однако стратегия, которой противоречит ваш процесс выпуска, порождает процесс, который все обходят стороной.
Непрерывная интеграция зависит от trunk-based
CI означает, что каждое изменение интегрировано и проверено, а возможно это лишь при коротких ветках. С ветками на неделю CI проверяет ветку, в которую больше никто не сливает, и любопытные отказы всплывают во время слияния — ровно тогда, когда разработчик уже переключился. Это и есть самый сильный практический довод за короткие ветки, и держится он даже в маленькой команде.
короткая ветка -> результат CI предсказывает слияние -> слияние скучное
длинная ветка -> CI зелёный, слияние — сюрприз -> слияние — событие
Выберите одну, запишите её и держите исключения явными
Любая стратегия работает, если команда следует ей последовательно. Крахом заканчивается смесь, о которой никто не договаривался: ветка выпуска, которую никто не сливает обратно, хотфикс, применённый в двух местах, develop, убежавший на три недели вперёд. Запишите правило в репозитории, назовите, кому можно создавать ветку выпуска, и требуйте, чтобы исключение объявляли вслух, а не подразумевали.
Практика
Измерьте время жизни своих веток
Посмотрите на последние двадцать слитых веток в своём репозитории и запишите, сколько каждая прожила от первого коммита до слияния.
Готово, когда: вы можете назвать медианное время жизни и сказать, соответствует ли это число стратегии, которой, как считает команда, она следует.
Попробуйте другую стратегию на одном изменении
Возьмите очередное небольшое изменение и за день интегрируйте его в ствол, а если оно не завершено — спрячьте за флагом. Отметьте, что пришлось сделать иначе, чем в обычном потоке.
Готово, когда: изменение попало в ствол за день, и вы можете назвать, что стратегия заставила вас решить раньше.
Частые ошибки
- Долгоживущие ветки функций — слияние превращается в многодневное событие, а сигнал CI устаревает; исправить: держите ветки короткими, а незавершённое прячьте за флагами.
- Внедрение GitFlow без поезда выпусков — develop и main расходятся без всякой пользы; исправить: выбирайте стратегию, которая вашему процессу выпуска действительно нужна.
- Develop, который никто не сливает обратно — работа копится, и итоговая интеграция становится отдельным проектом; исправить: сливайте вперёд по расписанию либо удалите ветку и переходите на ствол.
- Хотфикс в двух местах — одна и та же правка существует дважды, и одну копию забывают; исправить: правьте в стволе и продвигайте либо сделайте ветку хотфикса единственным путём.
- Незаписанная стратегия — каждый следует собственной, и исключения становятся нормой; исправить: запишите правило в репозитории и назовите, кому можно его нарушать.
Что читать дальше
- Git (система контроля версий) (01-cs-fundamentals/12-git) — объектная модель и механика слияния, на которых строится любая стратегия ветвления, поэтому читайте первым.
- GitHub (01-cs-fundamentals/23-github) — здесь ветки становятся pull request’ами, а стратегия встречается с ревью.
- Архитектура программного обеспечения (01-cs-fundamentals/25-software-architecture) — как форма развёртывания ограничивает набор возможных стратегий ветвления.