Как я могу перечислить все легкие теги?

Я хочу перечислить все легкие теги в моем репозитории; лучшее, что я могу придумать, включает в себя объединение git for-each-ref, grep и cut, но похоже, что это будет немного странно...

(Хотя мы и находимся в этом, мы можем поговорить об одном и том же для аннотированных тегов: кто-то наверняка закончит здесь, задаваясь вопросом об этом в какой-то момент.)

Edit:

В тегах lightweight я имел в виду те ссылки тегов, которые не относятся к объектам тегов. (Другими словами, unannotated tags.)

Ответ 1

Все легкие теги находятся в пространстве имен refs/tags/ и могут быть перечислены, например:

git for-each-ref --format '%(refname:short)' refs/tags/

или

git show-ref --tags

Как и для аннотированных тегов, ну, трюк здесь - он также влияет на часть "облегченных" тегов - это то, что аннотированный тег фактически является объектом в репозитории git, но есть легкий тег, который указывает на это объект, который позволяет вам получить аннотированный тег по имени его тега. 1 Так что это действительно пара вещей: легкий тег, плюс объект аннотированного тега in-repo, который делает его "не легкий тег", за исключением этого упрямого факта, что это легкий тег в одно и то же время!

Таким образом, это сводится к: найти все легкие теги, а затем при необходимости выбрать только теги, указывающие на фиксации или теги, указывающие на тег-объекты в зависимости от поведения, которое вы хотите, затем затем испускайте имя тега.

В документации git-for-each-ref для написания целых script в строке --format есть длинный пример и использование eval для его выполнения (или вы можете выполнить транзакцию до sh, за счет один дополнительный процесс). Мне обычно проще проложить вывод git for-each-ref в цикл while read ...:

git for-each-ref refs/tags/ --format '%(objecttype) %(refname:short)' |
    while read ty name; do [ $ty = commit ] && echo $name; done

который печатает теги только для легкого.

Сравните с:

git for-each-ref refs/tags/ --format '%(objecttype) %(refname:short)' |
    while read ty name; do [ $ty = tag ] && echo $name; done

который печатает все теги аннотированные (точнее, теги "легкие, которые являются аннотированными" ).

Обратите внимание, что тег может (возможно, нет реального использования для этого прямо сейчас, насколько я знаю) указывает на нечто иное, чем фиксация или тег; вам нужно сделать что-то с тегом, указывающим непосредственно на tree или blob.


1 Без легкого тега вы не сможете ссылаться на аннотированный тег annotag, используя имя annotag, не пройдя все усилия поиска, которые git fsck использует для найти повисшие объекты, по крайней мере. Более того, если вы удалите легкий тег, объект аннотированного тега может получить сбор мусора. Вы можете сделать один объект тега объекта другим тегом, чтобы сохранить его в репо (т.е. Запретить gc) без внешнего имени для второго объекта тега, если первое имеет внешнее имя. Это определенно странная вещь, чтобы сделать, хотя.

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