git describe видит тег локально, но не в CI: проверяем глубину истории

Локально git describe печатает v2.4-12-g..., а в GitLab CI завершается с сообщением об отсутствии имён для описания коммита. Ревизия исходников правильная. Разница может быть в объёме истории: runner получает shallow clone, где нужный тег или путь к помеченному коммиту отсутствует.

git describe ищет подходящий достижимый тег в графе коммитов. Ему недостаточно знать имя текущей ветки. Для вычисления версии нужен тот участок графа, который связывает HEAD с тегом. Если история обрезана раньше, локальный и CI-результаты различаются закономерно.

Начнём с прозрачной конфигурации

Для отдельной job вычисления версии можно отключить shallow history через GIT_DEPTH: "0". Пример рассчитан на репозиторий, где есть достижимый тег. Образ Alpine получает Git отдельной командой; доступ к репозиторию пакетов требуется при подготовке job.

describe-version:
  image: alpine:3.22
  variables:
    GIT_DEPTH: "0"
  before_script:
    - apk add --no-cache git
  script:
    - git rev-parse --is-shallow-repository
    - git describe --tags --long HEAD > version.txt
    - cat version.txt
  artifacts:
    paths: [version.txt]

Первый вывод должен быть false. Если ближайший подходящий тег — v2.4, а HEAD находится на двенадцать коммитов дальше, версия будет иметь форму v2.4-12-g<сокращённый SHA>. Конкретный суффикс определяется вашим графом. --long сохраняет расширенную форму даже на самом теге, где расстояние равно нулю.

Здесь --tags разрешает использовать также lightweight tags. Без него git describe по умолчанию рассматривает только annotated tags. Это отдельная возможная причина расхождения, которую нужно проверить до изменения глубины. Если команда в терминале и CI различается параметрами, полная история сама по себе не сделает результаты одинаковыми.

Получить теги и получить историю — разные вещи

Команда fetch --tags может добавить ссылки на теги, но shallow boundary всё ещё ограничит доступный граф. Для конкретного проекта можно углублять историю на известное число коммитов или снять ограничение. Полная история проще для начальной диагностики, но дороже для большого репозитория. После воспроизведения определите минимальный набор данных, необходимый алгоритму версии.

Не переносите GIT_DEPTH: "0" во все jobs автоматически. Проверке форматирования или сборке текущих файлов дальняя история может быть не нужна. Отдельная job версии создаёт маленький артефакт, который затем передаётся потребителям. Это делает стоимость полной истории локальной и сохраняет один вычисленный результат на pipeline.

Если нет ни одного подходящего тега, git describe всё равно завершится ошибкой при полной истории. Решите политику заранее: такой запуск запрещён для релиза либо получает иной идентификатор. Флаг --always даст fallback на SHA, но может молча изменить формат версии, ожидаемый упаковщиком. Используйте его только при согласованном контракте.

Теговый pipeline можно обработать отдельно

Если выпуск запускается непосредственно тегом, GitLab предоставляет CI_COMMIT_TAG. Это имя события, а не результат поиска ближайшего предка. Для релиза по точному тегу оно иногда лучше выражает задачу, чем git describe. Для обычного коммита эта переменная не является заменой алгоритма расстояния до предыдущего выпуска.

Проверьте три сценария: HEAD на теге, несколько коммитов после тега и ветка без достижимого тега. Ожидаемый статус и формат версии должны быть определены для каждого. Сохраняйте version.txt вместе с артефактом сборки, чтобы последующие jobs не вычисляли другой результат по своей копии истории.

В курсе GitLab CI/CD есть версионированные образы, registry и выпуск приложения. Откройте программу и продолжите к pipeline, где версия связана с конкретной ревизией и передаётся неизменной от проверки до публикации.

Ещё по теме

Продолжить на практике

  • GitLab CI/CD: автоматизация сборки и деплоя ↗

    От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.