164

When I enter a command:

git tag -l

I get such results:

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

Instead of this I want:

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

How it's possible to sort current list to get such results?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Viacheslav Kondratiuk
  • 8,493
  • 9
  • 49
  • 81
  • 1
    With Git 2.0, you will soon be able to do a `git tag -l --sort=version:refname "rc-*"`, and get the output you want. see [my answer below](http://stackoverflow.com/a/22634649/6309) – VonC Mar 25 '14 at 12:30
  • 2
    Git 2.0 is out now, and all the answers below using 'sort' are no longer needed. [`--sort` is available for git tag](http://stackoverflow.com/a/22634649/6309) – VonC Jun 18 '14 at 13:33

9 Answers9

232

Use version sort

git tag -l | sort -V

or for git version >= 2.0

git tag -l --sort=v:refname
git tag -l --sort=-v:refname # reverse
Robert Mutke
  • 2,757
  • 1
  • 16
  • 14
112

With Git 2.0 (June 2014), you will be able to specify a sorting order!

See commit b6de0c6, from commit 9ef176b, authored by Nguyễn Thái Ngọc Duy (pclouds):

 --sort=<type>

Sort in a specific order.
Supported type is:

  • "refname" (lexicographic order),
  • "version:refname" or "v:refname" (tag names are treated as versions).

Prepend "-" to reverse sort order.


So, if you have:

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

Here is what you would get:

# 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

Since commit b150794 (by Jacob Keller, git 2.1.0, August 2014), you can specific that default order:

tag.sort

This variable controls the sort ordering of tags when displayed by git-tag.
Without the "--sort=<value>" option provided, the value of this variable will be used as the default.

robinst comments:

the version sort order can now (Git 2.1+) be configured as default:

git config --global tag.sort version:refname

As noted by Leo Galleguillos in the comments:

To configure Git to show newest tags first (descending order), just add a hyphen before version.
The command becomes:

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

With Git 2.4 (Q2 2015), the versionsort.prerelease configuration variable can be used to specify that v1.0-pre1 comes before v1.0.

See commit f57610a by Junio C Hamano (gitster).

Note (see below) versionsort.prereleaseSuffix is now (2017) a deprecated alias for versionsort.suffix.


git 2.7.1 (February 2016) will improve the output of git tag itself.

See commit 0571979 (26 Jan 2016), and commit 1d094db (24 Jan 2016) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 8bad3de, 01 Feb 2016)

tag: do not show ambiguous tag names as "tags/foo"

Since b7cc53e (tag.c: use 'ref-filter' APIs, 2015-07-11), git tag has started showing tags with ambiguous names (i.e., when both "heads/foo" and "tags/foo" exists) as "tags/foo" instead of just "foo".
This is both:

  • pointless; the output of "git tag" includes only refs/tags, so we know that "foo" means the one in "refs/tags".
  • and ambiguous; in the original output, we know that the line "foo" means that "refs/tags/foo" exists. In the new output, it is unclear whether we mean "refs/tags/foo" or "refs/tags/tags/foo".

The reason this happens is that commit b7cc53e switched git tag to use ref-filter's "%(refname:short)" output formatting, which was adapted from for-each-ref. This more general code does not know that we care only about tags, and uses shorten_unambiguous_ref to get the short-name.
We need to tell it that we care only about "refs/tags/", and it should shorten with respect to that value.

let's add a new modifier to the formatting language, "strip", to remove a specific set of prefix components.
This fixes "git tag", and lets users invoke the same behavior from their own custom formats (for "tag" or "for-each-ref") while leaving ":short" with its same consistent meaning in all places.

If strip=<N> is appended, strips <N> slash-separated path components from the front of the refname (e.g., %(refname:strip=2) turns refs/tags/foo into foo.
<N> must be a positive integer.
If a displayed ref has fewer components than <N>, the command aborts with an error.

For git tag, when unspecified, defaults to %(refname:strip=2).


Update Git 2.12 (Q1 2017)

See commit c026557, commit b178464, commit 51acfa9, commit b823166, commit 109064a, commit 0c1b487, commit 9ffda48, commit eba286e (08 Dec 2016) by SZEDER Gábor (szeder).
(Merged by Junio C Hamano -- gitster -- in commit 1ac244d, 23 Jan 2017)

versionsort.prereleaseSuffix is a deprecated alias for versionsort.suffix.

The prereleaseSuffix feature of version comparison that is used in "git tag -l" did not correctly when two or more prereleases for the same release were present (e.g. when 2.0, 2.0-beta1, and 2.0-beta2 are there and the code needs to compare 2.0-beta1 and 2.0-beta2).

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • `--sort` doesn't exist on git 1.9.1. (worked on 2.0.0) – Tibor Vass Jun 04 '14 at 19:35
  • @TeaBee true, I have edited the answer accordingly, since Git 2.0 is released now. – VonC Jun 04 '14 at 19:45
  • 3
    With Git 2.1.0, the version sort order can now be configured as default: `git config --global tag.sort version:refname` – robinst Aug 24 '14 at 07:26
  • @robinst Good point, thank you. I have included it in the answer, with a link to the git commit which introduced that feature. – VonC Aug 24 '14 at 07:34
  • 1
    It would be worth explaining why this is better than `sort -V`. The only advantage I see is portability to systems that don't have GNU sort. But if you have it `| sort -V` golfs better. The thing is: this sort method does not use any Git-specific information (unlike e.g. topological order of object pointed to as in http://stackoverflow.com/questions/6900328/git-command-to-show-all-lightweight-tags-creation-dates) – Ciro Santilli OurBigBook.com Apr 27 '15 at 06:58
  • @CiroSantilli六四事件法轮功 I agree. I prefer the `git tag --sort` method though. – VonC Apr 27 '15 at 07:06
  • Interestingly, it understands both `customtext-1.1.0` and `1.1.0-customtext`. Sorts both flawlessly, assuming you just choose one format. Not really sure if it will work if you mix it, though I think it as a bad idea ;) – Ardee Aram Jul 03 '15 at 00:46
  • `git tag --sort=-taggerdate` to get the recently tag – deFreitas Jul 27 '16 at 15:17
  • To configure git to show newest tags first (descending order), just add a hyphen before `version`. The command becomes: `git config --global tag.sort -version:refname` – Leo Galleguillos May 25 '20 at 19:49
  • 1
    @LeoGalleguillos Thank you. I have included your comment in the answer for more visibility. – VonC May 25 '20 at 19:55
20

Combining the answers already here:

Local repository

git -c 'versionsort.suffix=-' tag --list --sort=-v:refname
  • suffix=- will prevent 2.0-rc coming "after" 2.0
  • --sort=- will put the highest version number at the top.

Remote repository

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

The advantage of this is that no objects are downloaded from the remote.

For more info see this answer.

Tom Hale
  • 40,825
  • 36
  • 187
  • 242
12

According to this answer, on platforms which don't support sort -V like Windows and OSX, you can use

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

Community
  • 1
  • 1
Cédric
  • 817
  • 10
  • 11
2

To get a reverse sorting with the sort -V approach:

git tag -l | sort -V --reverse
modle13
  • 1,242
  • 2
  • 16
  • 16
1

Adapt this perl script, which sorts tags that look like client_release/7.2/7.2.25, to your specific tagging scheme.

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
1

I ended up writing a simple shell script to simplify this task.

#!/usr/bin/env bash

TAGS=$(git tag)
CODE=$?

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

exit $CODE

I saved that as git-tags in my $PATH and run git tags whenever I need to list tags.

Kevin Herrera
  • 2,941
  • 3
  • 19
  • 13
1

If you're on Linux and using ZSH; Simply use gtl command. It should be predefined as an Alias for you.

Alias code:
gtl='gtl(){ git tag --sort=-v:refname -n -l "${1}*" }; noglob gtl'

SReza S
  • 151
  • 1
  • 9
-1

try list for special formate with last one

git tag -l --sort=refname | grep -E '^\d+\.\d+\.\d+.*' | tail -n 1

or first one

git tag -l --sort=refname | grep -E '^\d+\.\d+\.\d+.*' | head -n 1

Wei
  • 324
  • 3
  • 10