Git описывать два тега на одном и том же коммите

Мы иногда имеем два тега для одного и того же коммита. Когда мы используем git описать для этого фиксации, git описать всегда возвращает первый тег. Мое чтение справочной страницы git -describe, похоже, указывает на то, что второй тег должен быть возвращен (что имеет больше смысла).

  SEARCH STRATEGY
     For each committish supplied, git describe will first look for a tag which tags
     exactly that commit. Annotated tags will always be preferred over lightweight tags, 
     and tags with newer dates will always be preferred over tags with older dates. 
     If an exact match is found, its name will be output and searching will stop.

Есть ли способ вернуть git describe второй тег?

Ответ 1

Пробовали ли вы какие-либо опции git описать?

   --all
       Instead of using only the annotated tags, use any ref found in .git/refs/. This option enables
       matching any known branch, remote-tracking branch, or lightweight tag.

   --tags
       Instead of using only the annotated tags, use any tag found in .git/refs/tags. This option
       enables matching a lightweight (non-annotated) tag.

Ответ 2

Из всего, что я могу сказать, "git description" не может устранить неоднозначность легких тегов и поэтому печатает первый встреченный тег. В этом фрагменте предполагается, что теги следуют шаблону, сортируемому с помощью sort -R, и возвращают "последний" тег для данного SHA:

git tag --contains SHA | sort -R | tail -1

Ответ 3

Поведение Git в этом случае странное и запутанное.

Когда я делаю два тега для одного и того же коммита, я замечаю, что в .git/refs/tags у каждого из тегов есть свой коммит, поэтому теоретически можно однозначно извлечь точный тег.

На практике это не так.

Допустим, я совершил ABCD. Я делаю два тега к нему (аннотированный), v1.0 и v2.0.

У меня тогда есть что-то вроде этого..

master → ABCD hotfix → ABCD v1.0 (3423) → ABCD v1.0 (4234) → ABCD

Когда я извлекаю ветку, такую как master или hotfix, я замечаю, что git просто сохраняет в .git/HEAD ссылку на ветку, так что все хорошо, это не неоднозначная, а конкретная ветка.

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

Когда вы извлекаете тэг, такой как v1.0 или v2.0, HEAD не будет содержать тэг ref или тэг commit, а вместо этого будет идентификатор id, как если бы вы извлекли коммит напрямую!

В этом случае возникает путаница: если вы извлекаете ветку, такую как master, то при проверке тега, состояния git и description вы увидите правильный тег, который вы извлекли, даже если он неоднозначный!

Однако если вы затем извлечете другой тег, указывающий на то же самое, он покажет исходный тег. Переключение с ветки на тег запоминает тег, переключение с тега на тег - нет.

Я не знаю, является ли это ошибкой или как Git даже делает это (я предполагаю, что это повторяется (.git/logs/HEAD), но, учитывая, что поведение выглядит произвольным, я рискну предположить, что если вы просто хотите используйте команду, чтобы получить то, что пользователь выбрал сверху вниз, будь то тег, ветвь или фиксация, тогда я не думаю, что это надежно поддерживается.

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

Облегченные теги (не аннотированные, сами не имеют коммитов, являются просто указателем на коммит) ведут себя так же странно. Учитывая, что он в состоянии сохранить именно то, где пользователь извлечен в одном случае, но в другом случае произошел сбой, я бы предложил, чтобы это было ошибкой, о которой следует сообщать.

Вариант использования для этого заключается в том, что пользователь проверяет только одну вещь, даже если этот идентификатор может указывать на что-то со многими другими идентификаторами. Для удобства вы хотите получить идентификатор, который пользователь вставил для использования в качестве идентификатора, например, для сборки. Способность помнить этот идентификатор необъяснимо противоречива.

В этом случае ваши сценарии должны будут попытаться получить единственный лучший идентификатор, но если идентификатор неоднозначный, это должно привести к ошибке. Вы не можете полагаться на такие вещи, как состояние git или описание, так как иногда они не будут генерировать то, что было в последний раз извлечено, как видно при переходе от тега к тегу, а не переходить к тегу.

Это можно увидеть в .git/logs/HEAD который, кажется, содержит отчеты о переходах по тэгам, но как только вы попали в тэг, ничего не регистрируется.

Похоже, Describe всегда возвращает самый последний аннотированный (не легкий) тег. Если вы смешиваете типы тегов, вы не должны принимать последовательное поведение. Облегченные теги, по-видимому, также используют самую последнюю версию (предположительно, основанную на --all времени файла, а не на времени фиксации), но не ищутся без --all или --tags. Даже с --all аннотированные теги имеют преимущество перед более поздними облегченными тегами.

Единственный удобный способ получить все идентификаторы для текущего тега, который я могу найти, - это запустить git show-ref с разыменованием и выполнить grep для вашего текущего коммита. Это не будет включать метки времени для сортировки.