Слияние, теги и релизы: как отслеживать, что попадает в продакшен

Вы только что закончили ревью пул-реквеста. Код выглядит хорошо, тесты проходят, коллега одобрил изменения. Что дальше?

Большинство команд знают, что нужно смержить изменения в основную ветку. Но то, как именно вы выполняете слияние, какие записи оставляете и как помечаете то, что работает в продакшене, — всё это определяет, сможет ли ваша команда через полгода ответить на простой вопрос: «Какой код был реально развёрнут в такую-то дату?»

Merge-коммит — ваша бумажная тропа

Есть несколько способов объединить изменения из фиче-ветки с основной веткой. Самый распространённый — создание merge-коммита.

Merge-коммит делает больше, чем просто переносит код. Он фиксирует два куска информации: из какой ветки пришли изменения и в какую ветку они попали. Это создаёт чёткую запись в истории коммитов, которая говорит: «Здесь было слияние».

Сравните это с fast-forward слиянием, когда Git просто перемещает указатель вперёд, не создавая нового коммита. Fast-forward слияния делают историю линейной, но теряют контекст того, что слияние произошло. Если позже понадобится отследить баг до его источника, merge-коммит даёт прямую ссылку на обсуждение пул-реквеста, комментарии к ревью и точные изменения, которые объединились.

Когда вы используете merge-коммиты, ваш git log рассказывает историю. Вы видите, что feature-x была смержена в main во вторник, а feature-y — в среду. Если в четверг что-то ломается, вы точно знаете, какое слияние проверять в первую очередь.

Следующая диаграмма показывает, как каждый шаг связывается в чёткую бумажную тропу:

flowchart TD A[Feature Branch] --> B[Merge Commit] B --> C[Delete Feature Branch] C --> D[Create Tag: v1.2.0] D --> E[Generate Release Notes] E --> F[Deploy to Production] B -.-> G[Branch Info: source & target] D -.-> H[Permanent reference point] F -.-> I[Traceable to merge commit]

Вот точная последовательность команд после одобрения пул-реквеста:

# 1. Merge with a non-fast-forward merge commit
git checkout main
git merge --no-ff feature-x -m "Merge feature-x into main"

# 2. Tag the release on the merge commit
git tag -a v1.2.3 -m "Release v1.2.3"

# 3. Push main and the new tag to the remote
git push origin main --tags

# 4. Delete the feature branch locally and remotely
git branch -d feature-x
git push origin --delete feature-x

Уборка после слияния

Как только слияние завершено, фиче-ветка выполнила свою задачу. Удаление ветки поддерживает репозиторий в чистоте и не даёт старым веткам засорять список, когда кому-то нужно создать новую.

Некоторые команды удаляют ветки сразу после слияния. Другие ждут день-два, пока новая версия поработает в продакшене, — на случай, если понадобится создать hotfix-ветку из той же точки. Любой подход работает, главное — придерживаться единой практики.

Перед удалением убедитесь, что все изменения из этой ветки действительно попали в основную. Быстрая проверка: если ветка была смержена через пул-реквест, большинство Git-платформ покажут её как «merged» и позволят удалить одним кликом.

Теги: даём версиям имена

Теперь ваша основная ветка содержит последний код. Но как узнать, какой именно коммит работает в продакшене прямо сейчас? Основная ветка движется вперёд с каждым новым изменением. Без фиксированной точки отсчёта вы гадаете.

Здесь на помощь приходят теги. Тег — это метка, привязанная к конкретному коммиту. В отличие от веток, теги не перемещаются. Создав тег, он навсегда указывает на тот самый коммит.

Команды обычно создают теги при выпуске новой версии. Например, после завершения тестирования и готовности к развёртыванию в продакшене они создают тег вроде v1.2.0 на последнем коммите основной ветки. Этот тег становится постоянной ссылкой. Через полгода, если кто-то спросит, какой код работал в такую-то дату, вы проверяете тег.

Именование тегов: единообразие

Имена тегов должны следовать соглашению, понятному всей команде. Семантическое версионирование — популярный выбор: v1.2.3, где:

  • Первое число меняется для мажорных релизов, нарушающих обратную совместимость
  • Второе число — для новых функций
  • Третье число — для исправлений ошибок и небольших улучшений

Но семантическое версионирование — не единственный вариант. Некоторые команды используют даты: release-2024-11-15. Другие — номера сборок: build-142. Важна последовательность. Выберите формат, задокументируйте его и используйте для каждого релиза.

Какой бы формат вы ни выбрали, убедитесь, что тег создан именно с того коммита, который был развёрнут. Если вы пометите другой коммит, тег потеряет ценность как надёжная точка отсчёта.

Релиз-ноуты: что изменилось и почему

После создания тега большинство команд пишут релиз-ноуты. Релиз-ноут — это краткое описание того, что изменилось в этой версии. Он не должен быть длинным или детальным. Он должен отвечать на вопрос: «Стоит ли мне обратить внимание на этот релиз?»

Хорошие релиз-ноуты включают:

  • Новые функции, которые заметят пользователи
  • Исправления ошибок, решающие известные проблемы
  • Критические изменения, требующие действий от других команд или пользователей
  • Известные проблемы или ограничения в этой версии

Релиз-ноуты не обязательно писать с нуля. Многие команды генерируют их из заголовков пул-реквестов или сообщений коммитов между последним тегом и текущим. Быстрый просмотр, чтобы убрать технические детали и добавить контекст для пользователя, обычно достаточен.

Мост между разработкой и продакшеном

Слияние и тегирование образуют мост между написанием кода и его работой в продакшене. Слияние гарантирует, что проверенные изменения попадают в общую кодовую базу. Тег гарантирует, что вы можете указать на конкретный коммит и сказать: «Это версия, работающая прямо сейчас».

Без тегов у вас длинная история коммитов и нет способа узнать, какие из них были реально выпущены. Вы начинаете гадать, проверять логи развёртывания или спрашивать коллег, которые могут не помнить. Теги устраняют эту неопределённость.

Практический чек-лист

Перед следующим релизом выполните эти шаги:

  • Выполните слияние пул-реквеста с merge-коммитом, а не fast-forward
  • Удалите фиче-ветку после подтверждения слияния
  • Создайте тег на том самом коммите, который будет развёрнут
  • Напишите релиз-ноуты с описанием изменений и их важности
  • Убедитесь, что тег отправлен в удалённый репозиторий, чтобы вся команда его видела

Что это значит для вашей команды

В следующий раз, когда вы будете сливать пул-реквест, подумайте о том, что вы оставляете после себя. Merge-коммит и тег — это маленькие действия, но они создают историю, за которую ваш будущий «я» скажет спасибо. Когда в 2 часа ночи что-то пойдёт не так и нужно будет узнать, что изменилось, вам не придётся гадать. У вас будет чёткий след от проблемы в продакшене до merge-коммита, пул-реквеста и обсуждения, которое привело к изменению.