rzaripov.kz

Почему Git Flow стал моим стандартом в Delphi-разработке

Когда я начинал карьеру разработчика под Delphi, вопрос выбора системы контроля версий и модели ветвления решался легко — никто вокруг толком не пользовался ничем, кроме личных папок с архивами и периодических копий на флешку. Сейчас всё иначе: кроссплатформенные проекты на FireMonkey требуют согласованной работы между Windows, macOS, Android и iOS, а сроки релизов сжались. Git Flow дал мне понятный каркас, который одинаково хорошо работает и для сольных проектов, и для небольших команд, где я одновременно выступаю архитектором, разработчиком и тестировщиком.

За последние годы я неоднократно пересматривал свои подходы и пробовал GitHub Flow, GitLab Flow, trunk-based development — у каждой модели есть сильные стороны. Разберу подробнее, почему именно Git Flow остаётся той схемой, которая лучше всего ложится на жизненный цикл коммерческого ПО, где между стабильной версией и активной разработкой часто лежат месяцы поддержки. Ниже расскажу, какие нюансы я учитываю именно при работе с Delphi и FireMonkey.

Что такое Git Flow и в чём его суть

Git Flow — это модель ветвления, предложенная Винсентом Дриссеном в 2010 году. Она описывает набор фиксированных веток с понятными ролями: master хранит релизы, develop собирает текущую разработку, feature-ветки изолируют новые возможности, release-ветки готовят поставку, hotfix-ветки экстренно правят продакшен. Сопровождает модель одноимённая утилита-расширение для Git, которая автоматизирует открытие, завершение и слияние веток по конвенциям.

Для проектов на Delphi эта схема особенно удобна тем, что релиз — это не просто тег в репозитории, а собранный и проверенный дистрибутив для конкретной платформы. Выделенная ветка release даёт мне время на тестирование, обновление версии в .dproj, прогон автотестов, подготовку changelog и заодно позволяет держать develop чистым для следующих задач. Когда приходит сообщение об ошибке в опубликованной версии, я открываю hotfix от master, не отвлекаясь на текущую разработку.

Структура веток в моих Delphi-проектах

В реальной работе я придерживаюсь расширенного варианта Git Flow с дополнительной веткой support для долгоживущих клиентских версий. Связано это с тем, что часть заказчиков из финансового сектора Казахстана работает на конкретных сборках, которые я обязан сопровождать отдельно. master содержит только стабильные релизы с тегами вида v3.4.2, develop — снепшот текущего цикла, а из них вырастают feature, release и hotfix.

Имена веток я стараюсь делать осмысленными: feature/firemonkey-android-12-adapt, release/4.0-rc1, hotfix/crash-on-startup-linux. Это упрощает анализ истории и автоматическую маршрутизацию задач в CI. В файле .gitignore у меня скрыты локальные настройки RAD Studio, выходные папки скомпилированных бинарников и кэши LiveBindings — иначе дерево быстро зарастает мусором. Подробное описание моего рабочего стека и принципов ведения проектов собрано в каталоге работ.

Преимущества для кроссплатформенной FireMonkey-разработки

FireMonkey позволяет из одной кодовой базы собирать приложения под разные платформы, и здесь Git Flow помогает держать порядок. Условная директория Platform с подпапками Win, Mac, iOS, Android, Linux растёт с каждым проектом, и без изолированных веток изменения под одну платформу часто ломали сборку под другие. С feature-ветками я спокойно веду экспериментальную работу над Linux-версией, пока develop содержит стабильный код для Windows и macOS.

Отдельно стоит упомянуть работу с языковыми ресурсами и ассетами. Часто правка локализаций касается сразу нескольких проектов одного семейства, и здесь помогает регулярный rebase feature-ветки на develop перед слиянием — конфликты в .dfm и .fmx становятся заметны рано, а не в момент подготовки релиза. У других разработчиков я встречал иные подходы; например, в материалах Java D. Taghia описывается схожая философия изоляции изменений, но с акцентом на иные инструменты сборки.

Автоматизация сборки и тестирования через CI

Git Flow хорошо стыкуется с любыми CI-системами — Jenkins, GitLab CI, GitHub Actions. Я использую связку из Jenkins на собственном сервере и FastLane для сборки мобильных таргетов. Каждый пуш в feature-ветку запускает инкрементальную сборку под ту платформу, которой ветка касается, а develop и release прогоняются по полному матричному пайплайну — Windows, macOS, Android, iOS, Linux.

Скрипты сборки хранятся в корне репозитория в каталоге build, и их развитие идёт в собственных feature-ветках, как обычный код. Когда я меняю правила формирования версии или подписи APK, это отдельный запрос на слияние с ревью и тегами — никакой магии в Jenkins-файле, которую никто не контролирует. После слияния в develop CI сам подтягивает новые правила, и я вижу, как раскатывается свежая сборка. Утилита git-flow на этом этапе нужна только для ведения веток; всё остальное закрывает обычный Git.

Сравнение Git Flow с другими моделями ветвления

Я часто получаю вопрос, зачем такая «тяжёлая» модель для проекта, который ведёт один человек. Ответ прост — дисциплина. Даже соло-разработчику полезно иметь границу между кодом «в разработке» и кодом «в релизе», иначе через полгода сам автор перестаёт понимать, что стабильно, а что нет.

Модель Долгоживущих веток Поддержка релизов Сложность для соло Подходит для Delphi
Git Flow 2 (master, develop) Полноценная через release и hotfix Средняя Да, особенно при долгосрочной поддержке версий
GitHub Flow 1 (main) Через теги и feature-флаги Низкая Частично, для коротких релизных циклов
GitLab Flow 2 (main, environment) Гибкая, через окружения Низкая Да, если есть staging-сервер
Trunk-based 1 (main) Через feature flags и канареечные релизы Высокая Нет — Delphi плохо дружит с флагами в стиле A/B
Task branching Много коротких Отсутствует, заточено на эксперименты Низкая Слабо, нет стабильной ветки для пользователей

Trunk-based выглядит привлекательно в мире веб-сервисов, где A/B-тесты разворачиваются за минуты, но в настольных приложениях и мобильных сборках на Delphi такая практика оборачивается долгими откатами и невоспроизводимыми ошибками. GitHub Flow я применяю для небольших утилит и прототипов, где релизом удаётся заняться в тот же день.

Практические наблюдения и тонкости

За годы использования Git Flow у меня сложился набор привычек, которые я рекомендую всем, кто работает с Delphi и FireMonkey. Во-первых, я всегда проверяю, чтобы в release-ветке был свежий develop — это страхует от долгих merge-конфликтов в DFM-файлах. Во-вторых, hotfix я стараюсь мержить обратно и в master, и в develop одной операцией, иначе правка быстро теряется в текущей разработке.

Ещё один полезный приём — release-ветку я удаляю сразу после слияния в master и develop, потому что висящие ветки в RAD Studio IDE периодически создают путаницу в списке проектов. Теги для релизов я подписываю аннотированными, с коротким changelog прямо в сообщении тега — потом это экономит часы при подготовке клиентских отчётов. Собственно, ради этих мелочей я и держусь за Git Flow: модель даёт не столько готовые ответы, сколько единый язык, на котором со мной разговаривает собственный код спустя месяцы после написания.