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

463

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

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

вывод:

a
b
c

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

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

Ответы:

412

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

JB.
источник
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
acassis
источник
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)
kilianc
источник
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)говорили здесь: Как получить последнее имя тега?

xserrat
источник
Я начал с вершины / принятого ответа и прошел путь вниз. Это первый ответ, который на самом деле дает мне последний тег (не уверен почему, но обычный старый 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, а на пути, который расходится оттуда.

Мэтью Бретт
источник
21

git describe --tags

возвращает последний тег, видимый текущей веткой

beenhere4hours
источник
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на то, что вы хотите!

gavenkoa
источник
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
AechoLiu
источник
для меня это не вок, последний тег - 2.11.174, но этот вывод - 2.11.99, потому что сортировка не как
версия
8
git tag --sort=committerdate | tail -1
user2957741
источник
Пожалуйста, объясните, как этот фрагмент кода решит проблему, вместо того, чтобы публиковать ответ только для кода.
Арун Винот
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")
Scyssion
источник
3

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

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

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

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

v1.0.0

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

Markus
источник
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.

dohpaz42
источник
Ничто не гарантирует, что «самый последний тег» обрабатывается любой веткой. Двумя рабочими решениями являются 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говорит "соответствует только один", так что вы получите только самый последний тег.

jthill
источник
0

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

git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1
Clintm
источник
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