Теги, релизы и git cherry-pick

Завершаем курс двумя точечными приёмами: помечаем релизы тегами и переносим одиночные коммиты.

Теги: закладки на важных коммитах

Тег (tag) — неподвижная метка на конкретном коммите, обычно отмечающая версию релиза, например v1.0.0.

В отличие от ветки, тег не двигается: он навсегда указывает на один коммит. Это идеально для релизов — по тегу v2.3.0 вы всегда найдёте точное состояние кода, которое ушло в этот релиз.

Создание тегов

Есть два вида. Лёгкий (lightweight) — просто имя-указатель. Аннотированный (annotated) — полноценный объект с автором, датой и сообщением; для релизов рекомендуют именно его:

git tag v1.0.0                       # лёгкий тег
git tag -a v1.0.0 -m "Релиз 1.0.0"   # аннотированный (рекомендуется)

Посмотреть и изучить теги:

git tag                # список всех тегов
git show v1.0.0        # подробности тега и коммита

Отправка тегов на сервер

Важная тонкость: обычный git push теги не отправляет. Их нужно пушить отдельно:

git push origin v1.0.0     # один тег
git push origin --tags     # все теги сразу

На GitHub из тега удобно сделать Release — страницу с описанием версии, списком изменений и прикреплёнными файлами сборки. Releases строятся как раз поверх тегов.

git cherry-pick: перенести один коммит

git cherry-pick копирует один конкретный коммит из одной ветки в другую.

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

git switch release
git cherry-pick a1b2c3d

Вывод:

[release f7g8h9i] Исправить деление на ноль в калькуляторе
 1 file changed, 3 insertions(+), 1 deletion(-)

git создаст в текущей ветке новый коммит с теми же изменениями (хеш будет другим). Если возникнет конфликт — разрешаете его как обычно и продолжаете через git cherry-pick --continue.

cherry-pick с осторожностью

Не злоупотребляйте cherry-pick: если переносить им много коммитов, в истории появятся дубли (один и тот же фикс в двух ветках с разными хешами). Для систематического переноса работы лучше merge или rebase, а cherry-pick — для точечных, разовых случаев.

Семантическое версионирование

Имена тегов релизов обычно не случайны — они следуют схеме SemVer вида MAJOR.MINOR.PATCH, например 2.4.1. Правило простое: PATCH растёт при исправлении багов, MINOR — при добавлении совместимых функций, MAJOR — при несовместимых изменениях. Глядя на номер версии, пользователь сразу понимает масштаб изменений и риск обновления. Поэтому теги релизов почти всегда выглядят как v1.0.0, v1.2.0, v2.0.0.

Удаление и перенос тегов

Если тег поставлен по ошибке, его можно удалить — отдельно локально и на сервере:

git tag -d v1.0.0                    # удалить локально
git push origin --delete v1.0.0      # удалить на сервере

Менять уже опубликованный тег релиза — плохая идея: люди могли на него сослаться. Если в релизе нашли баг, выпускают новый тег (v1.0.1), а не переписывают старый.

Итог

  • Тег — неподвижная метка коммита для версий; для релизов используйте аннотированный (-a).
  • Теги пушатся отдельно: git push origin --tags.
  • git cherry-pick <хеш> копирует один коммит в текущую ветку — для точечного переноса.
Проверьте себя
1. Чем тег отличается от ветки?
AТег двигается за новыми коммитами, а ветка нет
BТег — неподвижная метка на одном коммите, а ветка — подвижный указатель
CТег можно создать только на сервере
DМежду ними нет разницы
2. Что произойдёт с тегами при обычном git push?
AОни отправятся вместе с коммитами автоматически
BТеги не отправляются; их нужно пушить отдельно (например, --tags)
CТеги удалятся с сервера
DPush завершится ошибкой
3. Что делает git cherry-pick a1b2c3d?
AСливает всю ветку с коммитом a1b2c3d
BКопирует один коммит a1b2c3d в текущую ветку как новый коммит
CУдаляет коммит a1b2c3d
DСоздаёт тег с именем a1b2c3d
Поддержать проект