Как отсортировать теги git по порядку строки версии в форме rc-XYZW?

110

Когда я ввожу команду:

git tag -l

Получаю такие результаты:

rc-0.9.0.0
rc-0.9.0.1
rc-0.9.0.10
rc-0.9.0.11
rc-0.9.0.12
rc-0.9.0.2
rc-0.9.0.3
rc-0.9.0.4
rc-0.9.0.5
rc-0.9.0.6
rc-0.9.0.7
rc-0.9.0.8
rc-0.9.0.9

Вместо этого хочу:

rc-0.9.0.0
rc-0.9.0.1
rc-0.9.0.2
rc-0.9.0.3
rc-0.9.0.4
rc-0.9.0.5
rc-0.9.0.6
rc-0.9.0.7
rc-0.9.0.8
rc-0.9.0.9
rc-0.9.0.10
rc-0.9.0.11
rc-0.9.0.12

Как можно отсортировать текущий список, чтобы получить такие результаты?

Вячеслав Кондратюк
источник
1
С Git 2.0 вы скоро сможете выполнить git tag -l --sort=version:refname "rc-*"и получить желаемый результат. см. мой ответ ниже
VonC
1
Git 2.0 уже вышел, и все ответы, приведенные ниже с использованием «сортировки», больше не нужны. --sortдоступно для тега git
VonC

Ответы:

158

Использовать сортировку по версиям

git tag -l | sort -V

или для версии git> = 2.0

git tag -l --sort=v:refname
git tag -l --sort=-v:refname # reverse
Роберт Мутке
источник
@miku проверьте пожалуйста! для меня это так
Роберт Мутке
5
Аргумент -V недоступен в версии sort (5.93), предоставляемой OS X (10.8). :(
Жюльен
2
вы можете использовать homebrew или macports для установки gnu-версии sort. brew install gsortтогда вы можете изменить строку выше на, git tag -l | gsort -Vи она должна работать на вас.
Горан
4
Пришлось использовать, brew install coreutilsчтобы получить gsortкоманду. brew install gsortне удалось, заявив, что посылка не вызывалась gsort.
nwinkler
Не повезло и с msysgit
cchamberlain
79

В Git 2.0 (июнь 2014 г.) вы сможете указать порядок сортировки!

См. Коммит b6de0c6 из коммита 9ef176b , автором которого является Nguy Thn Thái Ngọc Duy ( pclouds) :

 --sort=<type>

Сортировать в определенном порядке .
Поддерживаемый тип:

  • " refname" (лексикографический порядок),
  • " version:refname" или " v:refname" (имена тегов рассматриваются как версии).

Добавьте " -" к обратному порядку сортировки.


Итак, если у вас есть:

git tag foo1.3 &&
git tag foo1.6 &&
git tag foo1.10

Вот что вы получите:

# lexical sort
git tag -l --sort=refname "foo*"
foo1.10
foo1.3
foo1.6

# version sort
git tag -l --sort=version:refname "foo*"
foo1.3
foo1.6
foo1.10

# reverse version sort
git tag -l --sort=-version:refname "foo*"
foo1.10
foo1.6
foo1.3

# reverse lexical sort
git tag -l --sort=-refname "foo*"
foo1.6
foo1.3
foo1.10

Начиная с фиксации b150794 (Джейкоб Келлер, git 2.1.0, август 2014 г.), вы можете указать этот порядок по умолчанию:

tag.sort

Эта переменная управляет порядком сортировки тегов при отображении git-tag.
Если не указан параметр " --sort=<value>", значение этой переменной будет использоваться по умолчанию.

Робинст комментарии :

порядок сортировки версий теперь (Git 2.1+) можно настроить по умолчанию:

git config --global tag.sort version:refname

Как отметил в комментариях Лео Гальегийос :

Чтобы настроить Git на отображение новых тегов первымипорядке убывания), просто добавьте дефис перед версией .
Команда становится:

git config --global tag.sort -version:refname

С Git 2.4 (Q2 2015) , переменная конфигурации может использоваться для указания того, что предшествует .versionsort.prereleasev1.0-pre1v1.0

См. Коммит f57610a от Junio ​​C Hamano ( gitster) .

Примечание (см. Ниже) в versionsort.prereleaseSuffixнастоящее время (2017 г.) является устаревшим псевдонимом для versionsort.suffix.


git 2.7.1 (февраль 2016 г.) сам улучшит результат git tag.

См. Фиксацию 0571979 (26 января 2016 г.) и фиксацию 1d094db (24 января 2016 г.) Джеффом Кингом ( peff) .
(Объединено Junio ​​C Hamano - gitster- в коммите 8bad3de , 1 февраля 2016 г.)

tag: не показывать неоднозначные имена тегов как " tags/foo"

Начиная с b7cc53e ( tag.c: use ' ref-filter' API, 2015-07-11), git tagтеги с неоднозначными именами (т. Е. Когда существуют и " heads/foo", и " tags/foo" существуют) начали показывать как " tags/foo" вместо просто " foo".
Это оба:

  • бессмысленно; вывод " git tag" включает только refs/tags, поэтому мы знаем, что " foo" означает тот, который находится в " refs/tags".
  • и неоднозначно; в исходном выводе мы знаем, что строка " foo" означает, что " refs/tags/foo" существует. В новом выводе неясно, имеем ли мы в виду " refs/tags/foo" или " refs/tags/tags/foo".

Причина этого в том, что commit b7cc53e переключился git tagна использование " %(refname:short)" форматирования вывода ref-filter , которое было адаптировано из for-each-ref. Этот более общий код не знает, что нас интересуют только теги, и использует его shorten_unambiguous_refдля получения short-name.
Нам нужно сказать ему, что нас интересует только " refs/tags/", и он должен сокращаться по отношению к этому значению.

давайте добавим новый модификатор к языку форматирования " strip", чтобы удалить определенный набор компонентов префикса.
Это исправляет " git tag" и позволяет пользователям вызывать одно и то же поведение из своих собственных пользовательских форматов (для " tag" или " for-each-ref"), оставляя " :short" с одинаковым постоянным значением во всех местах.

Если strip=<N>добавлено, удаляет <N>компоненты пути, разделенные косой чертой, с начала имени ссылки (например, %(refname:strip=2)превращается refs/tags/fooв foo.
<N>Должно быть положительным целым числом.
Если отображаемая ссылка имеет меньше компонентов, чем <N>, команда прерывается с ошибкой.

Если git tagне указано иное, по умолчанию используется %(refname:strip=2).


Обновление Git 2.12 (первый квартал 2017 г.)

См. Фиксацию c026557 , фиксацию b178464 , фиксацию 51acfa9 , фиксацию b823166 , фиксацию 109064a , фиксацию 0c1b487 , фиксацию 9ffda48 , фиксацию eba286e (8 декабря 2016 г.) от SZEDER Gábor ( szeder) .
(Объединено Junio ​​C Hamano - gitster- в commit 1ac244d , 23 января 2017 г.)

versionsort.prereleaseSuffixявляется устаревшим псевдонимом для versionsort.suffix.

prereleaseSuffixФункция сравнения версии, которая используется в « git tag -l» не правильно , когда два или более prereleases для того же выпуск присутствовал (например , когда 2.0, 2.0-beta1и 2.0-beta2 там и потребность кода для сравнения 2.0-beta1и 2.0-beta2).

VonC
источник
--sortне существует в git 1.9.1. (работал над 2.0.0)
Тибор Васс
@TeaBee правда, я соответствующим образом отредактировал ответ, так как Git 2.0 выпущен сейчас.
VonC
1
В Git 2.1.0 порядок сортировки версий теперь можно настроить по умолчанию:git config --global tag.sort version:refname
robinst,
1
Стоит объяснить, почему это лучше, чем sort -V. Единственное преимущество, которое я вижу, - это переносимость на системы, в которых нет сортировки GNU. Но если есть | sort -Vгольф лучше. Дело в том, что этот метод сортировки не использует никакой информации, специфической для Git (в отличие, например, от топологического порядка объектов, на который указывает stackoverflow.com/questions/6900328/… )
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@LeoGalleguillos Спасибо. Я включил ваш комментарий в ответ для большей наглядности.
VonC
12

Согласно этому ответу , на платформах, которые не поддерживают, sort -Vнапример, Windows и OSX, вы можете использовать

git tag -l | sort -n -t. -k1,1 -k2,2 -k3,3 -k4,4

Седрик
источник
1
@ Ovi-WanKenobi вам нужно запустить его в оболочке Cygwin (или mingw).
Cédric
10

Объединив ответы уже здесь:

Локальный репозиторий

git -c 'versionsort.suffix=-' tag --list --sort=-v:refname
  • suffix=-предотвратит 2.0-rcприход "после"2.0
  • --sort=- поместит наивысший номер версии вверху.

Удаленный репозиторий

git -c 'versionsort.suffix=-' ls-remote -t --exit-code --refs --sort=-v:refname "$repo_url" \
    | sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g'

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

Для получения дополнительной информации см. Этот ответ .

Том Хейл
источник
Очень интересное использование versionsort.suffix. +1.
VonC
2

Чтобы получить обратную сортировку с sort -Vподходом:

git tag -l | sort -V --reverse
modle13
источник
1

Адаптируйте этот Perl-скрипт , который сортирует похожие теги client_release/7.2/7.2.25, к вашей конкретной схеме тегов.

Дэвид Тонхофер
источник
1

В итоге я написал простой сценарий оболочки, чтобы упростить эту задачу.

#!/usr/bin/env bash

TAGS=$(git tag)
CODE=$?

if [ $CODE = 0 ]; then
    echo "$TAGS" | sort -V
fi

exit $CODE

Я сохранил это как git-tagsв моем $PATHи запускаю git tagsвсякий раз, когда мне нужно перечислить теги.

Кевин Эррера
источник
2
git tag | sort -V; exit $ PIPESTATUS
luxigo