Как получить последнее имя тега в текущей ветке в Git?


463

Какой самый простой способ получить самый последний тег в Git?

git tag a HEAD
git tag b HEAD^^
git tag c HEAD^
git tag

вывод:

a
b
c

Должен ли я написать скрипт, чтобы получить дату и время каждого тега и сравнить их?


1
последний созданный тег или последний тег упорядочены по дате фиксации? Ваш принятый ответ показывает последний созданный тег. Это может быть проблемой, если кто-то решит изменить теги existig ...
— Paebbels

Ответы:


412

Вы могли бы взглянуть git describe, что делает что-то близкое к тому, что вы просите.


194
При --abbrev=0этом должен возвращаться ближайший аннотированный тег
— Jakub Narębski

13
Возвращает последний тег в текущей ветке.
— Бриттохаллоран

42
Чтобы получить последний аннотированный тег, предназначенный только для текущего коммита в текущей ветви , используйте git describe --exact-match --abbrev=0.
— Нафтули Кей

5
Этот ответ с комментариями не дал мне правильного тега. @kilianic предоставил правильное решение.
— Герман Дж. Радтке III

21
git describe --tagsи сравните последний тег на странице релиза github
— Adriano Resende

628

Чтобы получить самый последний тег:

git describe --tags

Чтобы получить самый последний аннотированный тег:

git describe --abbrev=0

2
Да, как git describeговорится на странице руководства : --abbrev=<n> [...] An <n> of 0 will suppress long format, only showing the closest tag.
— Giorgos Kylafas

22
Или простоgit describe --tags
— james_womack

5
Этот ответ (и, вероятно, другие) сталкивается с проблемами, если у вас есть два тега, указывающие на один и тот же коммит. Если теги не являются аннотированными тегами, я думаю, что у git нет способа отличить, какой из этих двух был создан ранее.
— Пол Линч

10
Это должен быть принятый ответ. Спасибо за отправку.
— crmpicco

6
если вы хотите напрямую git checkout $(git describe --abbrev=0 --tags)
— оформить

322

Выведет тэг последнего тегированного коммита во все ветви

git describe --tags $(git rev-list --tags --max-count=1)

8
или TAG=$(git describe --tags $(git rev-list --tags --max-count=1))@ william-pursell
— kilianc

20
Это лучший ответ. Он на самом деле получает теги во всех ветвях, а не только в текущей, как это делает текущий «правильный» ответ.
— Бриттохаллоран

61
За исключением вопроса, конкретно задает текущую ветку.
— michaeltwofish

3
@michaeltwofish, в то время, когда я этого не знал, я понял это позже и соответственно исправил свой ответ. Прости за это.
— kilianc

3
Примечания. Эта команда возвращает «новейший» тег, даже если этот тег находится в другой ветви.
— Алан Чжилян Фэн

47

Чтобы получить самый последний тег, вы можете сделать:

$ git for-each-ref refs / tags --sort = -taggerdate --format = '% (refname)' --count = 1

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


2
Это почти то, что я искал (самый последний тег во всех ветвях), но по крайней мере с моей версией git (1.7.7.6) теги производятся в одинаковом порядке для обоих --sort=-authordateи --sort=authordate.
— Жаворонки

3
Ага, потому что ты на самом деле хочешь --sort=-taggerdate. Для тегов authordateи committerdateпусто (так бесполезно, как ключи сортировки).
— Жаворонки

8
git for-each-ref refs/tags --sort=-taggerdate --format='%(refname:short)' --count=1еще лучше :)
— Кристоф Эбле

5
В самом деле, отрицательный ответ на совершенно правильный ответ, которому почти 5 лет, без комментариев? Это просто грубо.
— Уильям Перселл

1
И --points-at=$SHAдаст вам тег для хэша коммита.
— Райан

35

Как насчет этого?

TAG=$(git describe $(git rev-list --tags --max-count=1))

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


Этот не получает последний тег в текущей ветви, но для любых ветвей. Что здорово, потому что это именно то, что мне было нужно. Спасибо Винсент.
— jasongregori

2
Если вам нужно получить шаблон соответствия тега, вы можете использовать его --tags=<pattern>в rev-list. Например, получить тег последней версииgit describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)
— Wirone

1
$ (git description --contains $ (git rev-parse HEAD))
— Вайдас Зилионис

Спасибо, это сработало, но я должен был добавить --tags git describe --tags $(git rev-list --tags --max-count=1)
— Gianluca Casati

25

Вы можете выполнить: git describe --tags $(git rev-list --tags --max-count=1)говорили здесь: Как получить последнее имя тега?


Я начал с вершины / принятого ответа и прошел путь вниз. Это первый ответ, который на самом деле дает мне последний тег (не уверен почему, но обычный старый git describe ...возвращает более ранний тег ?!)
— Джереми Дэвис,

Это единственный, который работает для меня. Перепробовал некоторые --abbrev=0ответы, и они отрезали часть тега, который я хочу.
— Люк Дэвис

22

«Самый последний» может иметь два значения с точки зрения мерзавца.

Вы могли бы иметь в виду, «какой тег имеет самую последнюю дату создания», и большинство ответов здесь на этот вопрос. С точки зрения вашего вопроса, вы хотели бы вернуть тегc .

Или вы можете указать, «какой тег является самым близким в истории разработки к некоторой именованной ветви», обычно это ветвь, в которой вы находитесь HEAD. В вашем вопросе это вернет тегa .

Конечно, они могут отличаться:

A->B->C->D->E->F (HEAD)
       \     \
        \     X->Y->Z (v0.2)
         P->Q (v0.1)

Представьте тег разработчика Zкак v0.2в понедельник, а затем тег Qкак v0.1во вторник. v0.1он более свежий, но v0.2в истории развития он ближе к HEAD, в том смысле, что путь, по которому он идет, начинается с точки, близкой к HEAD.

Я думаю, что вы обычно хотите этот второй ответ, ближе в истории развития. Вы можете узнать это, используя git log v0.2..HEADetc для каждого тега. Это дает вам количество коммитов на HEAD, начиная с пути, заканчивающегося наv0.2 отличается от пути, по которому следует HEAD.

Вот скрипт Python, который делает это путем итерации всех тегов, выполняющих эту проверку, а затем распечатывает тег с наименьшим количеством фиксаций в HEAD, поскольку путь тега расходится:

https://github.com/MacPython/terryfy/blob/master/git-closest-tag

git describeделает что-то немного другое, в том смысле, что он отслеживает (например) HEAD, чтобы найти первый тег, который находится на пути назад в истории из HEAD. В терминах git git describeищет теги, которые «достижимы» из HEAD. Поэтому он не найдет такие теги, v0.2которые находятся не на пути назад от HEAD, а на пути, который расходится оттуда.



15
git log --tags --no-walk --pretty="format:%d" | sed 2q | sed 's/[()]//g' | sed s/,[^,]*$// | sed  's ......  '

ЕСЛИ ВАМ НУЖНО БОЛЬШЕ, ЧЕМ ОДИН ПОСЛЕДНИЙ ТЕГ

(git description --tags иногда выдает неправильные хэши, я не знаю почему, но для меня --max-count 2 не работает)

это то, как вы можете получить список с двумя последними именами тегов в обратном хронологическом порядке, отлично работает на git 1.8.4. Для более ранних версий git (например, 1.7. *) В выводе нет строки «tag:» - просто удалите последний вызов sed

Если вы хотите более 2 последних тегов - измените «sed 2q» на «sed 5q» или что вам нужно

Затем вы можете легко разобрать каждое имя тега в переменную или около того.


это действительно полезно, многие разработчики попытаются автоматизировать процесс выпуска, откатившись до предыдущего тега, если развертывание прервется. Крутые вещи !!!
— AkD

1
Для этого: git log --tags --no-walk --pretty="format:%D" | sed -nr '5q;s;^.*(tag: )([^,]*).*;\2;p' если in %Dисключает окружающие ()символы, а seds, начинающийся с 5q, оставляет 4 строки перед 5, затем выводит все символы между тегом: `и первым ','. Итак ... при условии, что внутри тега не используются запятые, это работает отлично.
— Cometsong

14

Что не так со всеми предложениями (кроме Мэтью Бретта объяснения , до даты публикации этого ответа)?

Просто запустите любую команду, предоставленную другим, в истории jQuery Git, когда вы находитесь в другой точке истории, и проверьте результат с помощью визуального представления истории тегов (я сделал это, поэтому вы видите этот пост):

$ git log --graph --all --decorate --oneline --simplify-by-decoration

Сегодня многие проекты выполняют релизы (и т. Д. С тегами) в отдельной ветке от основной линии. .

Есть веские причины для этого. Просто посмотрите на любые хорошо известные JS / CSS проекты. Для пользовательских соглашений они несут двоичные / минимизированные файлы выпуска в DVCS. Естественно, как сопровождающий проекта, вы не хотите очищать свою историю различий в магистрали бесполезными двоичными двоичными объектами и выполнять фиксацию артефактов сборки из магистрали. .

Поскольку Git использует DAG, а не линейную историю - трудно определить метрику расстояния, поэтому мы можем сказать - о, эта скорость самая близкая к моей HEAD!

Я начинаю свое собственное путешествие (загляните внутрь, я не копировал причудливые доказательства в этот длинный пост):

Что является ближайшим тегом в прошлом относительно ветвления в Git?

В настоящее время у меня есть 4 разумных определения расстояния между тегом и ревизией с уменьшением полезности:

  • длина кратчайшего пути от HEADдо слияния базы с тегом
  • дата от слияния базы между HEADи тегов
  • количество оборотов , достижимых из HEAD, но не доступных из тега
  • дата тега независимо от базы слияния

Я не знаю, как рассчитать длину кратчайшего пути .

Сценарий , что сортировать тег в соответствии с датой от слияния базы между HEADи тегов:

$ git tag \
     | while read t; do \
         b=`git merge-base HEAD $t`; \
         echo `git log -n 1 $b --format=%ai` $t; \
       done | sort

Это применимо на большинстве проектов.

Скрипт, который сортирует теги по количеству оборотов, которые достижимы из HEAD, но недоступны из тегов:

$ git tag \
    | while read t; do echo `git rev-list --count $t..HEAD` $t; done \
    | sort -n

Если в истории вашего проекта есть странные даты коммитов (из-за перебазировок или другой перезаписи истории, или какой-то придурок забыл заменить батарею BIOS или другую магию, которую вы делаете в истории), используйте сценарий выше.

Для последнего варианта ( дата тега независимо от базы слияния ), чтобы получить список тегов, отсортированных по дате, используйте:

$ git log --tags --simplify-by-decoration --pretty="format:%ci %d" | sort -r

Чтобы узнать текущую дату ревизии, используйте:

$ git log --max-count=1

Обратите внимание, что git describe --tagsони используются в отдельных случаях, но не для поиска ожидаемого человеком ближайшего тега в истории проекта .

ПРИМЕЧАНИЕ. Вы можете использовать вышеперечисленные рецепты в любой ревизии, просто замените HEADна то, что вы хотите!


12

git describe --abbrev=0 --tags

Если вы не видите последний тег, убедитесь, что он извлекает источник перед запуском:

git remote update


12
git tag -l ac* | tail -n1

Получить последний тег с префиксом «ac» . Например, тег с именем ac1.0.0или ac1.0.5. Другие теги , названные 1.0.0, 1.1.0будут игнорироваться.

git tag -l [0-9].* | tail -n1

Получить последний тег, чей первый символ 0-9. Таким образом, эти теги с первым символом a-zбудут игнорироваться.

Больше информации

git tag --help # Help for `git tag`

git tag -l <pattern>

Перечислите теги с именами, которые соответствуют заданному шаблону (или всем, если шаблон не указан). Запуск «git tag» без аргументов также перечисляет все теги. Шаблон является подстановочным знаком оболочки (то есть сопоставляется с помощью fnmatch (3)). Может быть дано несколько шаблонов; если какой-либо из них совпадает, тег отображается.


tail -n <number> # display the last part of a file
tail -n1 # Display the last item 

Обновить

С git tag --help, об sortаргументе. Он будет использоваться lexicorgraphic orderпо умолчанию, если tag.sortсвойство не существует.

Порядок сортировки по умолчанию равен значению, настроенному для переменной tag.sort, если она существует, или лексикографическому порядку в противном случае. Смотрите git-config (1).

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

git tag --sort=committerdate

для меня это не вок, последний тег - 2.11.174, но этот вывод - 2.11.99, потому что сортировка не как
— версия

8
git tag --sort=committerdate | tail -1

Пожалуйста, объясните, как этот фрагмент кода решит проблему, вместо того, чтобы публиковать ответ только для кода.
— Арун Винот

5

Следующее работает для меня, если вам нужны последние два тега (например, для создания журнала изменений между текущим тегом и предыдущим тегом). Я проверял это только в ситуации, когда последний тег был HEAD.

PreviousAndCurrentGitTag=`git describe --tags \`git rev-list --tags --abbrev=0 --max-count=2\` --abbrev=0`
PreviousGitTag=`echo $PreviousAndCurrentGitTag | cut -f 2 -d ' '`
CurrentGitTag=`echo $PreviousAndCurrentGitTag | cut -f 1 -d ' '`

GitLog=`git log ${PreviousGitTag}..${CurrentGitTag} --pretty=oneline | sed "s_.\{41\}\(.*\)_; \1_"`

Это соответствует моим потребностям, но, поскольку я не волшебник, я уверен, что это может быть улучшено. Я также подозреваю, что он сломается, если история коммитов продвинется вперед. Я просто делюсь на случай, если это кому-нибудь поможет.


4

Моя первая мысль, что вы можете использовать git rev-list HEAD, который перечисляет все обороты в обратном хронологическом порядке, в сочетании с git tag --contains. Когда вы найдете ссылку, где git tag --containsсоздается непустой список, вы нашли самые последние теги.


4

Если вы хотите найти последний тег, который был применен к определенной ветви, вы можете попробовать следующее:

git describe --tag $(git rev-parse --verify refs/remotes/origin/"branch_name")

3

Если вам нужен один вкладыш, который получает последнее имя тега (по дате тега) в текущей ветви :

git for-each-ref refs/tags --sort=-taggerdate --format=%(refname:short) --count=1 --points-at=HEAD

Мы используем это, чтобы установить номер версии в настройке.

Пример вывода:

v1.0.0

Работает и на Windows тоже.


1
На Linux (Debian Stretch) я получаю-bash: syntax error near unexpected token '('
— Джереми Дэвис

1
Если я оберну эту часть в кавычки (то есть --format="%(refname:short)") и пропущу --points-at=HEADэто работает. С этим последним переключателем он ничего не возвращает, я думаю, потому что мой HEADне помечен?
— Джереми Дэвис

@ JeremyDavis, да, я думаю, что это потому, что ваш HEADне помечен.
— Маркус

2

Это старая ветка, но, похоже, многим не хватает самого простого, простого и правильного ответа на вопрос OP: чтобы получить последний тег для текущей ветки , вы используете git describe HEAD. Выполнено.

Редактировать: вы также можете указать любое правильное имя, даже удаленное; т.е. git describe origin/masterскажет вам последний тег, который может быть достигнут от origin / master.


Ничто не гарантирует, что «самый последний тег» обрабатывается любой веткой. Двумя рабочими решениями являются for-each-refкоманда ( stackoverflow.com/a/5261470/515973 ) и комбинация rev-listи describe( stackoverflow.com/a/7979255/515973 )
— Жюльен Карсик,

1
Это не самый последний тег для меня.
— К - Токсичность в СО растет.

git describe branchname --tagsу меня работает, чтобы получить последний тег на ветке (git версия 2.12.2)
— Rob_M

0

Чтобы получить последний тег только для текущей ветви / имени тега, в котором используется префикс текущей ветви, мне пришлось выполнить следующее

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags --abbrev=0 $BRANCH^ | grep $BRANCH

Отраслевой мастер:

git checkout master

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

master-1448

Филиал таможенный:

git checkout 9.4

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

9.4-6

И мое последнее необходимо увеличить и получить тег +1 для следующего тегирования.

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags  --abbrev=0 $BRANCH^ | grep $BRANCH | awk -F- '{print $NF}'

0

На вопрос, как задано,

Как получить последнее имя тега в текущей ветке

ты хочешь

git log --first-parent --pretty=%d | grep -m1 tag:

--first-parentговорит git logне детализировать какие-либо объединенные истории, --pretty=%dговорит показывать только декорации, т.е. локальные имена для любых коммитов. grep -m1говорит "соответствует только один", так что вы получите только самый последний тег.


0

если ваши теги сортируются:

git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1

0

Не так много упоминаний о аннотированных тегах и аннотированных здесь. «description» работает с аннотированными тегами и игнорирует аннотированные.

Это некрасиво, но делает запрошенную работу и не найдет никаких тегов в других ветвях (а не в теге, указанном в команде: master в приведенном ниже примере)

Фильтрация должна быть оптимизирована (консолидирована), но, опять же, это похоже на работу.

git log  --decorate --tags master |grep '^commit'|grep 'tag:.*)$'|awk '{print $NF}'|sed 's/)$//'|head -n 1

Критика приветствуется, так как я собираюсь сейчас использовать это :)


-2

Еще один простой способ получить последнее имя тега -

git tag | tail -1

или

TAG=$(git tag | tail -1)

хранить его в переменной.

git tagперечисляет все доступные теги и возвращает самый последний ряд, если результат.tail-1


4
Без сортировки это плохой ход.
— MJD2
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.