Как я могу перечислить все легкие теги?
Я хочу перечислить все легкие теги в моем хранилище; лучшее, что я могу придумать, включает в себя объединение git for-each-ref
, grep
, а также cut
, но кажется, что это будет немного странно...
(В то время как мы находимся на этом, мы могли бы также говорить об одном и том же для аннотированных тегов: кто-то обязательно в конечном итоге задумается об этом в какой-то момент.)
Редактировать:
От lightweight
теги, я имел в виду те ссылки на теги, которые не относятся к объектам тегов. (Другими словами, аннотированные теги.)
4 ответа
Все легкие метки находятся в refs/tags/
пространство имен и может быть перечислено, например:
git for-each-ref --format '%(refname:short)' refs/tags/
или же:
git show-ref --tags
Что касается аннотированных тегов, то здесь есть хитрость - она также влияет на часть "облегченных" тегов - это то, что аннотированный тег на самом деле является объектом в репозитории git, но есть легкий тег, который указывает на этот объект, что позволяет вам получить аннотированный тег по имени тега. 1 Так что это действительно пара вещей: легкий тег и добавленный в репо аннотированный теговый объект, который делает его "не легким тегом", за исключением того упрямого факта, что это легкий тег в то же время!
Таким образом, все сводится к следующему: найти все легкие теги, затем при необходимости выбрать только теги, указывающие на коммиты, или теги, указывающие на объекты тегов, в зависимости от желаемого поведения, а затем продолжить выдавать имя тега.
Есть длинный пример в git-for-each-ref
документация написания всего сценария в --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) без внешнего имени для второго объекта тега, если первый из них имеет внешнее имя. Хотя это определенно странная вещь.
Интересно, что внутренний формат для аннотированного тега содержит внешнее имя, поэтому можно использовать эту технику для защиты "старых" аннотированных тегов, скрыть их, удалив их легкие теги, а затем восстановить исходный облегченный тег. Может ли кто-нибудь придумать, как использовать это, хотя...:-)
Чтобы перечислить только легкие теги:
git for-each-ref refs/tags | grep commit
Чтобы перечислить только аннотированные теги:
git for-each-ref refs/tags | grep -v commit
Объяснение:
git for-each-ref
перечисляет все ссылки: головы , пульты , тайник и теги
git for-each-ref refs/tags
перечисляет только теги refs.
| grep commit
перечисляет только те строки, которые содержат слово фиксация . Это теги, указывающие на фиксацию и, следовательно, легкие теги.
| grep -v commit
перечисляет только те строки, которые не содержат слова фиксация . Это теги, указывающие на тег, и, следовательно, аннотированные теги.
Подводя итог другому ответу и его комментариям, если вы используете bash:
function git-lightweight-tags() {
git for-each-ref refs/tags/ --format '%(objecttype) %(refname:short)' | awk '$1 == "commit" {print $2}' ;
}
Имейте в виду, что вы также можете пометить (упрощенные и аннотированные) капли и деревья.
Поэтомуgit for-each-ref refs/tags | grep -v commit
будет не только перечислять аннотированные теги, но и теги для больших двоичных объектов и деревьев.
Я предлагаю использовать grep для слова «тег», чтобы найти аннотированные теги:
git for-each-ref refs/tags | grep -w tag
.
Не забывайте-w
, иначе вы найдете подстрокуtag
также для облегченных тегов.