Я уже не раз порывался написать что‑то общее про бранчинг; про некогда распиаренный GitFlow, который запиаривают обратно; про trunk‑based development (умеренно распиаривают), про то, как это увязать с разработкой бэкенда. И вот я затираю очередной забуксовавший черновик своей заметки с целью всё упростить и не гоняться за чрезмерным обобщением опыта. Давайте я просто поделюсь рецептом, а вы его оцените.
Обозначим ситуацию. Под небольшой апп нужно разработать небольшой бэк. Пара дизайнеров, от двух до пяти мобильщиков/фронтендеров, от двух до пяти человек на бэке, РП, аналитик, девопс, какое‑нибудь начальство — средний проект на полгода‑год‑два, короче. Я таких повидал уже несколько, и в половине подключался на середине жизненного цикла. И может, я не самый везучий и/или не самый опытный, но с бранчингом и средами всегда была какая‑то пускай не задница, но ложка дёгтя. Типа вроде всё нормально, но вот эту полную фигню мы обсуждать и исправлять не будем.
Фигнёй этой было назначение «нижних» общих сред. Если с самой верхней средой всё понятно (это святой продакшен), то с самой нижней всё очень мутно. Обзывают общие среды по‑разному, но я приведу самый частый паттерн: production, staging, development. Вот, например, даже целый Микрософт этот паттерн в своём фреймворке признаёт:
![Из доков по ASP.NET Core 7.0IsEnvironment уже не про конкретную среду Из доков по ASP.NET Core 7.0IsEnvironment уже не про конкретную среду](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/371/17b/594/37117b5949bbc26baa6b42de0a6b4ffe.png)
IsEnvironment
уже не про конкретную средуИ вот приходишь ты на очередной проект и спрашиваешь у ребят: как бранчуемся? Или не спрашиваешь если в репе лежит BRANCHING.md, но такой документ я лишь сам составлял. И тебе отвечают что‑то в духе «у нас GitFlow, мы делаем бранчи от develop, а дальше смотри вот эту пикчу если ещё не видел». Ну и дальше ты видишь в сотый раз эту пикчу.
![](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/2fd/d73/639/2fdd73639522abda4a2cad255743c74c.png)
И конечно же выясняется, что ветка develop соответствует нижней среде, ниже которой ничего нет. Соответствует в том смысле, что попадающие туда коммиты улетают в облака и проливаются над какой‑нибудь зоной типа https://api.dev.chebur.net.example/... (поэтично, да?)
Но постойте! Братцы! Если любой новый кодинг идёт от develop и это же ваша самая нижняя среда, то где вы экспериментируете? Где вы ловите баги за пределами юнит‑тестов? Ах да, я надеюсь, что у вас есть юнит‑тесты (naïve). И как вы поддерживаете стабильность develop? куда вы деваете недоделанную хрень, попавшую в develop, если вы потом от него пляшете? Извините, накипело.
В ответ звучит что‑нибудь про непонимание GitFlow, про заморозку кода перед релизом, про ещё какую‑нибудь тропинку огородами да гаражами оправдывающую ветвление от бранча, который завязан на экспериментальную по своей природе среду. Ну или отрицание самой идеи latest‑среды с недотестированными фичами.
Однажды меня осенило. Ну, в рамках своих проектов, конечно же; не претендую на открытие формулы всего: никакой ложки нижней среды на вон той диаграмме не существует, и она вообще не отвечает на вопрос долгоживущих сред. И лишь по недоразумению development‑среда оказывается develop‑бранчем под протухшим соусом GitFlow. Та пикча вообще не про бэкенд, который не сильно‑то тяготеет к версионированию.
Оставалось признать очевидное: нужна песочница, playground, workbench — как хотите называйте — которая и станет самой нижней средой. Если запретить ветвление от неё (в неё — можно), если запретить целиком выкатывать её в staging и дальше в production, то всё встаёт на свои места. Появляется общий энв со свежайшим кодом, который разблокирует фронтендеров, который позволяет самому увидеть свой код in action (апихи живые постманом подёргать), и который никого ни к чему не обязывает. Он по определению нестабилен. Точнее, стабилен ровно настолько, насколько позволяет юнит‑тестирование и насколько вообще может быть стабильна свежая фича.
Но если нельзя бранчеваться от dev|elop|ment потому что это какой‑то инкубатор, то откуда и как это делать? Давайте проследим через постепенное усложнение. Допустим, у нас есть только продакшен в облаках и единственный долгоживущий бранч в репозитории — main — на который продакшен и завязан. И пропустим вариант, где мы тупо фигачим все коммиты в main не создавая веток. Итак, простейший workflow:
![Нет, это не TBD Нет, это не TBD](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/2e6/345/3f4/2e63453f4bcd5e0257fcd1427fa2e21f.png)
Перфекшен! Если бы все всё делали идеально, то большего не нужно. И trunk‑based development как раз проповедует: никаких долгоиграющих веток! фигачим всё в ствол, понемногу и часто! любые сомнения заметаем под ковёр из фича‑тогглов! Но что если мы не готовы так радикально перестраиваться? Что если у нас не всё хорошо с тестами? Что если реальность требует где‑то вне продакшена проверять изменения?
Окей, добавим staging, где будем эти изменения копить и проверять. Почковаться разрешим хоть от main, хоть от staging. Типа если хочешь хотфикс сделать и проверить его на staging, то работай от main — так ты сможешь вмёрджить хотфикс в прод не утаскивая туда весь недоваренный staging. Ну а если в staging много почти готового накопилось, а тебе поверх этого надо новую фичу пилить — бранчуйся от staging, всё равно в конце спринта это всё вместе выкатывать.
![](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/4cf/551/ed2/4cf551ed29c5e24ae0af9b232e0abcb3.png)
Но тут приходит фронт и говорит, что им нужна свежая апиха, над которой ты ещё работаешь, чтобы вживую всё проверить. Или приходит бэк (может даже ты сам) и говорит, что подкрутил чего‑то в инфраструктурных скриптах и локально это не проверить вообще никак, надо накатить куда‑то. Этим «куда‑то» и становится development.
![](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/974/4ce/8c5/9744ce8c5b956524cabe05cd040e67c4.png)
В этой диаграмме важно то, что она вообще никак не изменила предыдущую. Она просто объявила среду совместной разработки (в плане доступности свежего кода в живой среде). Общий верстак, на котором можно допиливать полуготовый код. И эта среда по умолчанию нестабильно, и двигать её целиком вверх на staging или prod нельзя, и вообще можно с неё всё смахнуть (договорившись с командой) и начать с чистого листа — ну мало ли чего там брошенного накопилось.
Бардак? Ну да, можно смотреть как на бардак. Но можно смотреть как на компромисс и реальный способ обуздать косячную реальность. Да‑да, лучше сразу не косячить и всё такое. Где вы это видели? Возьмите меня туда учиться.
Идею можно развивать дальше и вместо одной песочницы объявить эфемерные среды, где можно поднять свою маленькую изолированную песочницу из любой ветки.
![](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/7b6/edf/3a5/7b6edf3a5a7af4a9d941aa8dc2f05965.png)
В теории это даже позволяет отказаться от staging, потому что проверять всё можно независимо и потом лить в продакшен тоже независимо.
![](https://webcf.waybackmachine.org/web/20231201021637/https://habrastorage.org/getpro/habr/upload_files/cf1/514/918/cf1514918cd6f6a294a8381f77161f0e.png)
Но это уже фантазии, до воплощения которых я не добирался. Предвижу, что это потребует качественного генератора тестовых данных и очень генерализованного CI/CD. Тестировщики, привыкшие к фиксированным средам, тоже спасибо не скажут. Оставим эту тему на другой раз.
Активирую режим подытоживающей интроспекции. Писать про то, как ты раз за разом сталкивался со стрёмными паттернами, неловко и обидно — что же это за работа такая грязная. Разбавлять это какими‑то компромиссными решениями неловко вдвойне. Но мне норм; и даже моя команда не против описанного подхода. Признав песочницу песочницей, мы перестали спорить о её стабильности. Да, она имеет свойство засоряться, но теперь это блокирует только её саму, а не возможность выкатить обновления в прод.