Поведение 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, а вместо идентификатора коммита, как если бы вы извлекли коммит напрямую!
В этом случае возникает путаница: если вы извлекаете ветку, такую как master, то при проверке тега, состояния git и description вы увидите правильный тег, который вы извлекли, даже если он неоднозначный!
Если вы затем извлечете другой тег, указывающий на то же самое, он покажет оригинальный тег. Переключение с ветки на тег, запоминает тег, переключение с тега на тег - нет.
Я не знаю, является ли это ошибкой или как Git даже делает это (я предполагаю, что это повторяется (.git / logs / HEAD), но, учитывая, что поведение выглядит произвольным, я рискну предположить, что если вы просто хотите использовать команду, чтобы получить то, что пользователь выбрал сверху вниз, будь то тег, ветвь или фиксация, тогда я не думаю, что это надежно поддерживается.
Если вы пытаетесь использовать команду для автоматического доступа к версии, то вам нужно будет либо вручную ввести тег пользователем, либо использовать какую-то процедуру для устранения коллизий.
Легкие теги (не аннотированные, сами не имеют коммита, являются просто указателем на коммит) ведут себя таким же странным образом. Учитывая, что он в состоянии сохранить именно то, где пользователь зарегистрировался в одном случае, а в другом - не удалось, я бы предложил, что это ошибка, о которой следует сообщить.
Вариант использования этого заключается в том, что пользователь проверяет только одну вещь, даже если этот идентификатор может указывать на что-то со многими другими идентификаторами. Для удобства вы хотите получить идентификатор, который пользователь вставил для использования в качестве идентификатора, например, для сборки. Способность Git запомнить этот идентификатор необъяснимо противоречива.
В этом случае ваши сценарии должны будут попытаться получить единственный лучший идентификатор, но если идентификатор неоднозначный, это должно привести к ошибке. Вы не можете полагаться на такие вещи, как состояние git или описание, поскольку иногда они не будут генерировать то, что было в последний раз извлечено, как видно при переключении с тега на тег, а не переходить на тег.
Это можно увидеть в .git/logs/HEAD
, который, кажется, содержит отчеты о переходах по тегам, но как только вы попали в тег, ничего не регистрируется.
Describe всегда возвращает самый последний аннотированный (не легкий) тег. Если вы смешиваете типы тегов, вы не должны принимать последовательное поведение. Облегченные теги, по-видимому, также используют самую последнюю версию (предположительно, основанную на отметке времени файла, а не на времени фиксации), но не ищутся без --all
или --tags
. Даже с параметром --all аннотированные теги имеют преимущество перед более поздними облегченными тегами.
Единственный удобный способ получить все идентификаторы для текущего тега, который я могу найти, - это запустить git show-ref с разыменованием и выполнить grep для вашего текущего коммита. Это не будет включать метки времени для сортировки.