Мы иногда имеем два тега для одного и того же коммита. Когда мы используем git описать для этого фиксации, git описать всегда возвращает первый тег. Мое чтение справочной страницы git -describe, похоже, указывает на то, что второй тег должен быть возвращен (что имеет больше смысла).
Ответ 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 для вашего текущего коммита. Это не будет включать метки времени для сортировки.