Отправка тегов на сервер git push --tags

17 декабря 2025
Автор

Олег Марков

Введение

Работа с тегами в Git часто кажется второстепенной задачей по сравнению с ветками и коммитами. Но именно теги помогают фиксировать важные точки в истории проекта – релизы, стабильные версии, экспериментальные сборки. Когда вы начинаете работать в команде и использовать удаленные репозитории, встает практический вопрос: как отправить все локальные теги на сервер, чтобы остальные участники могли их увидеть и использовать.

Здесь на сцену выходит команда git push --tags. Смотрите, я покажу вам, как она работает, какие у нее подводные камни и когда лучше выбрать более точечные команды, а не слепо отправлять все подряд.

В статье вы разберетесь:

  • какие бывают теги в Git и чем они отличаются;
  • что именно делает git push --tags и зачем он нужен;
  • как отправлять теги выборочно;
  • как удалять или переопределять теги на сервере;
  • как встроить работу с тегами в процесс релизов.

Что такое теги в Git и зачем их отправлять на сервер

Зачем вообще нужны теги

Тег в Git – это "ярлык", который указывает на конкретный коммит. В отличие от веток, теги не двигаются вперед при новых коммитах, а навсегда "приклеены" к одной точке истории.

На практике теги чаще всего используют для:

  • пометки релизов – v1.0.0, v2.3.5 и т.п.;
  • фиксации критичных состояний – before-migration, stable-2024-01;
  • совместной работы с CI/CD – запуск сборки или деплоя по тегу;
  • воспроизведения конкретного состояния проекта.

Чтобы этим тегом могли пользоваться другие разработчики или автоматизированные системы (CI, деплой-сервера), его нужно отправить в удаленный репозиторий – на GitHub, GitLab, Bitbucket или ваш корпоративный сервер.

Типы тегов – аннотированные и легковесные

Git поддерживает два основных типа тегов. Давайте разберемся, в чем разница, потому что это важно для понимания, какие теги вы отправляете на сервер.

Легковесный тег (lightweight tag)

Это просто имя, указывающее на коммит. Никакой дополнительной информации.

Создание:

# Создаем легковесный тег v1.0.0 для текущего коммита
git tag v1.0.0

Особенности:

  • не содержит автора, даты, сообщения;
  • по сути – это просто ссылка на hash коммита;
  • создается быстро, но мало метаданных.

Аннотированный тег (annotated tag)

Это полноценный объект в базе Git. Он хранит:

  • имя тега;
  • ссылку на коммит;
  • автора тега;
  • дату;
  • сообщение (аннотацию);
  • опционально – подпись GPG.

Создание:

# Создаем аннотированный тег с сообщением
git tag -a v1.0.0 -m "Первый стабильный релиз"

Комментарий к команде:

# -a  - создаем аннотированный тег
# v1.0.0 - имя тега
# -m "..." - сообщение тега, хранится в Git как описание

В большинстве командных процессов для релизов используют именно аннотированные теги. Они информативнее и лучше интегрируются с инструментами релизов и подписи релизов.

Почему git push не отправляет теги по умолчанию

Важный момент: когда вы делаете обычный git push, Git отправляет коммиты и обновления веток, но не все ваши теги.

Стандартный git push:

git push origin main

Отправляет:

  • все новые коммиты, которые появились в ветке main;
  • обновляет указатель ветки main на сервере.

Но локально созданные теги останутся только у вас, пока вы явно не отправите их в удаленный репозиторий.

Здесь и появляется потребность в командах вида:

  • git push origin <tagname> – отправить один тег;
  • git push origin --tags – отправить все локальные теги, которых нет на сервере.

Давайте теперь разберем, как именно работает git push --tags.

Как работает git push --tags

Базовый синтаксис и поведение

Команда:

git push --tags

по умолчанию эквивалентна:

git push origin --tags

если у вас настроен удаленный репозиторий origin и он используется по умолчанию.

Что делает эта команда:

  • находит все локальные теги, которые существуют в вашем репозитории;
  • сверяет их с тегами в удаленном репозитории;
  • отправляет те теги, которых еще нет на сервере;
  • не удаляет и не изменяет уже существующие теги на сервере.

Обратите внимание: git push --tags не перезаписывает теги в удаленном репозитории, если там уже есть тег с таким именем. Если локальный тег и удаленный тег с тем же именем указывают на разные коммиты, Git обычно откажется "тихо" их перезаписать, потребуется явная перезапись.

Пример с несколькими тегами

Давайте разберемся на примере небольшой истории:

# Создаем несколько аннотированных тегов
git tag -a v1.0.0 -m "Релиз 1.0.0"
git tag -a v1.1.0 -m "Релиз 1.1.0"
git tag -a v2.0.0-rc1 -m "Release candidate 2.0.0"

# Отправляем коммиты в основную ветку
git push origin main

# Теперь отправляем все теги разом
git push origin --tags

Комментарии:

# Первая команда создаст три аннотированных тега в вашей локальной репе
# git push origin main отправит только коммиты и обновит ветку main
# git push origin --tags отправит все локальные теги, которых еще нет в origin

После выполнения git push origin --tags все три тега появятся на сервере. В интерфейсе GitHub или GitLab вы увидите их в списке Releases или Tags (в зависимости от интеграции).

Взаимодействие с конфигурацией push.default

Параметр push.default в Git управляет тем, какие ветки отправляются при git push без указания имени ветки. На теги он не влияет напрямую.

Например:

git config --global push.default simple

Задаёт стратегию отправки веток, но теги все равно нужно отправлять отдельно:

git push
git push --tags

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

git push && git push --tags

или использовать алиас.

Создание алиаса:

git config --global alias.pushtags "push --tags"

Теперь вы можете использовать:

git pushtags

как короткую команду для отправки всех тегов.

Что будет, если теги уже есть на сервере

Если вы повторно выполните:

git push origin --tags

Git просто проверит, что все теги уже есть в удаленном репозитории, и ничего нового не отправит. Ошибок не будет, команда отработает быстро.

Это означает, что команду git push --tags можно запускать безопасно несколько раз. Она не удалит существующие теги и не перепишет их.

Выборочная отправка тегов

Иногда вам не нужно отправлять вообще все теги. Например, у вас есть множество тестовых тегов, и вы хотите отправить только релизные. В этом случае git push --tags будет слишком грубым инструментом.

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

Самая базовая команда:

# Отправляем один конкретный тег
git push origin v1.2.0

Комментарии:

# origin - имя удаленного репозитория
# v1.2.0 - имя тега, который должен существовать локально

Эта команда:

  • отправит тег v1.2.0 в репозиторий origin;
  • не затронет другие теги и ветки.

Отправка нескольких тегов по имени

Если нужно отправить несколько тегов сразу, но не все:

git push origin v1.0.0 v1.1.0 v2.0.0-rc1

Здесь вы явно перечисляете, какие теги должны уйти в удаленный репозиторий.

Комбинация веток и тегов

Git позволяет в одной команде отправить и ветки, и теги:

git push origin main v1.0.0 v1.1.0

Комментарии:

# Сначала будет отправлена ветка main
# Затем будут отправлены теги v1.0.0 и v1.1.0

Это удобно, если ваш релизный процесс выглядит так:

  1. Вы сделали коммиты в main.
  2. Пометили релиз тегом v1.2.0.
  3. Одной командой отправили и ветку, и тег.

Работа с шаблонами и выборкой тегов

Иногда удобнее оперировать группами тегов, а не перечислять их вручную. Например, у вас есть:

  • теги релизов: v1.0.0, v1.1.0, v2.0.0;
  • теги кандидатов в релиз: v2.0.0-rc1, v2.0.0-rc2;
  • внутренние теги: internal-test-1, internal-test-2.

Использование refspec для выборки тегов

git push позволяет использовать refspec – правило, описывающее, какие ссылки отправлять. Для тегов это может выглядеть так:

# Отправляем только теги, начинающиеся с v2.
git push origin 'refs/tags/v2.*:refs/tags/v2.*'

Комментарии:

# 'refs/tags/v2.*'    - все теги, имя которых начинается с v2.
# :refs/tags/v2.*     - куда их поместить на сервере (тот же путь)
# Кавычки нужны, чтобы оболочка не интерпретировала звездочку

Это более продвинутый сценарий, но он полезен, если вы хотите:

  • отправлять только релизные теги;
  • не трогать внутренние или экспериментальные теги.

Фильтрация тегов перед отправкой

Часто проще сначала посмотреть, какие теги у вас вообще есть.

Список всех тегов:

git tag

Список с фильтром:

# Все теги, начинающиеся с v1.
git tag -l "v1.*"

# Все теги, содержащие rc
git tag -l "*rc*"

Комментарии:

# -l "шаблон" - вывод тегов по шаблону
# Шаблон работает примерно как подстановка в shell

После того, как вы увидели нужные теги, можно отправить их выборочно:

git push origin v1.0.0 v1.1.0 v1.2.0

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

git push --tags не удаляет и не переписывает теги на удаленном репозитории. Но иногда вам нужно:

  • удалить ошибочный тег;
  • переместить тег на другой коммит (например, вы ошиблись с релизом).

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

Удаление тега в локальном и удаленном репозитории

Предположим, вы создали тег v1.0.0 не на тот коммит. Для начала нужно удалить его локально:

# Удаляем тег локально
git tag -d v1.0.0

Комментарии:

# -d - удалить тег из локального репозитория
# Эта команда не трогает удаленный репозиторий

Теперь нужно удалить тот же тег на сервере. Смотрите, я покажу вам, как это сделать с помощью git push:

# Удаляем тег в удаленном репозитории
git push origin :refs/tags/v1.0.0

Комментарии:

# Слева от двоеточия пусто  - это "источник" удаления
# Справа refs/tags/v1.0.0   - удаленный тег, который нужно удалить
# Фактически мы говорим  "отправить пустоту в этот тег"

Более короткий синтаксис (поддерживается в современных Git):

git push origin --delete v1.0.0

Комментарии:

# origin - удаленный репозиторий
# --delete v1.0.0 - удалить тег v1.0.0 на сервере

Переопределение (перемещение) тега

Если тег уже есть на сервере и вы хотите, чтобы он указывал на другой коммит, простой git push --tags не поможет, потому что он не перезаписывает существующие теги.

Алгоритм:

  1. Удалить тег на сервере.
  2. Пересоздать тег локально на нужном коммите.
  3. Снова отправить тег.

Пример:

# 1. Удаляем тег локально
git tag -d v1.0.0

# 2. Создаем новый тег v1.0.0 на нужном коммите
git tag -a v1.0.0 <commit-hash> -m "Исправленный релиз 1.0.0"

# 3. Удаляем старый тег на сервере
git push origin --delete v1.0.0

# 4. Отправляем новый тег
git push origin v1.0.0

Комментарии к важным моментам:

# <commit-hash> - хеш коммита, на который должен указывать тег
# Сначала нужно удалить тег на сервере, иначе Git может отказаться его перезаписать

В некоторых командах используют принудительную отправку тегов с --force, но для тегов такой подход менее прозрачен. Я рекомендую явное удаление и пересоздание – так вы лучше контролируете изменения.

Особенности и подводные камни git push --tags

Опасность "засорить" репозиторий тегами

Если вы активно создаете временные или экспериментальные теги локально, команда git push --tags отправит и их тоже. В результате:

  • удаленный репозиторий будет переполнен незначимыми тегами;
  • другим разработчикам будет сложно ориентироваться в списке тегов;
  • CI/релизные процессы могут случайно реагировать на лишние теги.

Чтобы избежать этого, лучше разделять:

  • локальные рабочие теги (например, с префиксом tmp-, experiment-);
  • "официальные" теги, которые действительно должны попасть на сервер.

И отправлять только нужные:

git push origin v1.2.0

или использовать шаблоны и выборочные команды.

Ситуация, когда тег указывает на коммит, которого нет на сервере

Интересный случай: вы создали тег на коммите, который еще не отправлен в удаленный репозиторий.

Например:

# Новый коммит, пока только локально
git commit -am "Новая фича"

# Тег на этом коммите
git tag -a v1.3.0 -m "Релиз 1.3.0"

# Отправляем только тег
git push origin v1.3.0

Что произойдет:

  • Git отправит тег v1.3.0;
  • автоматически отправит и коммит (и его родителей), на который указывает этот тег.

То есть при отправке тега Git всегда заботится о том, чтобы тег не "висел в воздухе" – соответствующий коммит тоже попадает на сервер.

Поэтому часто хватает одной команды:

git push origin v1.3.0

без отдельного git push origin main, если ваша цель – именно релиз по тегу.

Взаимодействие с ветками и зеркальным пушем

Иногда в проектах используют "зеркальный" пуш:

git push --mirror origin

Эта команда синхронизирует:

  • все ветки;
  • все теги;
  • все ref’ы.

Важно понимать: --mirror может удалить теги и ветки в удаленном репозитории, если вы удалили их локально. Это уже намного более "опасный" режим, чем git push --tags.

Для обычного рабочего процесса, когда вы просто хотите отправить теги на сервер, лучше использовать именно:

git push origin --tags

или выборочные:

git push origin v1.4.0

Практические сценарии использования тегов и git push --tags

Типичный релизный процесс с тегами

Давайте посмотрим, как выглядит простой, но понятный процесс релиза с использованием тегов:

  1. Вы завершили разработку фич в ветке main.
  2. Все тесты прошли, код готов к релизу.
  3. Вы создаете аннотированный тег v1.0.0.
  4. Отправляете ветку и тег на сервер.
  5. CI-система по тегу собирает и деплоит релиз.

Пошагово в командах:

# 1. Убеждаемся, что локальная ветка main актуальна
git checkout main
git pull origin main

# 2. Делаем последний коммит, если нужно
git commit -am "Подготовка к релизу v1.0.0"

# 3. Создаем аннотированный тег
git tag -a v1.0.0 -m "Релиз версии 1.0.0"

# 4. Отправляем ветку и тег в origin
git push origin main
git push origin v1.0.0

Комментарии:

# Здесь мы явным образом отправляем только релизный тег v1.0.0
# git push origin --tags тоже бы сработал, но отправил бы все локальные теги

Массовая отправка исторических тегов

Представьте, что вы:

  • долго работали с локальным репозиторием;
  • отмечали релизы тегами только у себя;
  • позже подключили удаленный репозиторий.

Теперь вы хотите "подтянуть" все исторические теги в origin.

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

git push origin --tags

Результат:

  • все существующие локальные теги уйдут на сервер;
  • история ваших релизов станет видна всей команде.

Если вы волнуетесь из-за временных тегов, имеет смысл:

  1. Посмотреть список тегов.
  2. Удалить заведомо лишние.
  3. Только потом сделать git push origin --tags.

Пример:

# 1. Смотрим все теги
git tag

# 2. Удаляем временные теги
git tag -d tmp-experiment-1
git tag -d tmp-experiment-2

# 3. Отправляем оставшиеся теги
git push origin --tags

Интеграция с CI/CD по тегам

Во многих CI-системах (GitHub Actions, GitLab CI, Jenkins, etc.) можно настроить запуск задач при появлении нового тега.

Пример – файл .gitlab-ci.yml:

release-job:
  stage: deploy
  script:
    - echo "Deploy по тегу"
    - ./deploy.sh  # Скрипт деплоя
  only:
    - tags  # Запускать только при пуше тега

Комментарии:

# only: - tags  - эта настройка говорит GitLab
# "запускать job, только когда появляется новый тег"

В таком процессе команда git push origin --tags может неожиданно запустить множество задач, если у вас накопилось много тегов, которые еще не были отправлены. Поэтому для CI лучше:

  • использовать выборочный пуш тегов;
  • или настраивать CI на работу только с тегами определенного вида (например, v*).

Рекомендации по использованию git push --tags

Суммируя практику, давайте сформулируем несколько рекомендаций.

Когда удобно использовать git push --tags

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

В таких сценариях git push --tags экономит время и не создает проблем.

Когда лучше не использовать git push --tags

  • в больших командах, где у разработчиков могут быть свои временные теги;
  • если вы часто создаете локальные технические теги;
  • если CI запускается на каждый новый тег.

В этих случаях безопаснее отправлять теги выборочно:

git push origin v3.0.0

или небольшими группами.

Локальная дисциплина именования тегов

Хорошая практика – договориться о формате тегов:

  • релизы: vX.Y.Z (например, v1.0.0);
  • кандидаты: vX.Y.Z-rcN (например, v2.0.0-rc1);
  • горячие фиксы: vX.Y.Z-hotfixN.

Тогда:

  • можно смело отправлять все теги v* в удаленный репозиторий;
  • а временные теги называть, например, tmp-*, user-* и не пушить их.

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

git push origin 'refs/tags/v*:refs/tags/v*'

Здесь вы явно говорите "отправить теги, имя которых начинается с v".

Заключение

Команда git push --tags решает понятную задачу – отправить все локальные теги в удаленный репозиторий. Она помогает:

  • быстро синхронизировать историю релизов;
  • перенести проект на новый сервер;
  • сделать все ваши "ярлыки" на коммиты доступными команде и CI-системам.

Однако у нее есть особенности:

  • по умолчанию отправляются все локальные теги, в том числе временные;
  • команда не удаляет и не перезаписывает существующие теги на сервере;
  • для тонкого контроля чаще используют выборочный пуш тегов.

Если вы понимаете различие между аннотированными и легковесными тегами, умеете удалять и переопределять теги в локальном и удаленном репозитории и осознанно используете git push --tags, работа с релизами и историей проекта становится более прозрачной и предсказуемой.


Частозадаваемые технические вопросы по теме и ответы

Как отправить только аннотированные теги и не отправлять легковесные

Прямой встроенной команды "push только аннотированные теги" в Git нет, но можно сделать это в два шага:

  1. Получить список аннотированных тегов:
git for-each-ref refs/tags --format="%(objecttype) %(refname:short)" | grep "^tag " | awk '{print $2}'

Комментарии:

# git for-each-ref ... - выводит все ссылки в refs/tags
# grep "^tag "         - фильтрует только аннотированные теги
# awk '{print $2}'     - берет только имя тега
  1. Отправить их:
git push origin $(<список-аннотированных-тегов>)

На практике проще изначально использовать аннотированные теги для релизов, а легковесные – как временные и не пушить их вообще.

Как посмотреть, какие теги еще не отправлены на сервер

Можно сравнить локальные и удаленные теги:

# Локальные теги
git tag > local-tags.txt

# Теги на сервере (после git fetch --tags)
git fetch origin --tags
git tag -l > remote-tags.txt

Дальше используйте утилиту diff:

# Какие теги есть локально, но нет на сервере
grep -Fxv -f remote-tags.txt local-tags.txt

Комментарии:

# git fetch origin --tags - подтягивает все теги с сервера, не меняя локальные
# grep -Fxv ... - выводит строки, которых нет во втором файле

Как запретить перезапись тегов на сервере другими разработчиками

На уровне Git-сервера обычно можно настроить "protected tags". Например, в GitLab:

  1. Зайдите в Settings – Repository – Protected tags.
  2. Укажите шаблон тегов, например v*.
  3. Разрешите их создание только определенным ролям и запретите перезапись.

На уровне "чистого" Git можно использовать update-хуки на сервере, которые будут отклонять попытки изменения уже существующих тегов.

Почему git push --tags не удаляет теги на сервере, которые я удалил локально

git push --tags только добавляет новые теги на сервер, но не синхронизирует удаление. Логика такая же, как и для веток без флага --prune. Чтобы удалить тег на сервере, нужно:

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

Или использовать refspec с удалением:

git push origin :refs/tags/v1.0.0

Как склонировать репозиторий сразу со всеми тегами

При обычном git clone теги тоже скачиваются, но лучше явно обновить их:

git clone <url> project
cd project
git fetch --tags

Комментарии:

# git clone по умолчанию забирает теги, связанные с загруженными коммитами
# git fetch --tags полезен, если позже были добавлены новые теги
Стрелочка влевоПросмотр тегов в Git - команды и практические примеры

Постройте личный план изучения Git до уровня Middle — бесплатно!

Git — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Git

Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы Git

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий