How to get last tag from a (non checked-out) remote repo?
On my local copy I use describe
git describe --abbrev=0 --tags
But I cannot use describe with remote storage
How to get last tag from a (non checked-out) remote repo?
On my local copy I use describe
git describe --abbrev=0 --tags
But I cannot use describe with remote storage
On
Unfortuntely, git ls-remote --tags actually lists tags alphabetically (at least as of 1.7.2.5). So, at the time that 1.7.10, 1.7.11 or 1.7.12 were the latest tags, 1.7.9 would have been the last on the list:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."
[...]
bf68fe0313c833fa62755176f6e24988ef7cf80f refs/tags/v1.7.9.6
cb2ed324fc917db0b79d7b1f3756575ffa5f70d5 refs/tags/v1.7.9.6^{}
3996bb24c84013ec9ce9fa0980ce61f9ef97be4d refs/tags/v1.7.9.7
d0f1ea6003d97e63110fa7d50bb07f546a909b6e refs/tags/v1.7.9.7^{}
However, we can pipe these results through 'sort' to get closer to the results we're looking for:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."| sort -g -k3 -t.
[...]
eab05abaeb51531e11835aaa4c26564a1babebac refs/tags/v1.7.9-rc2
eac2d83247ea0a265d923518c26873bb12c33778 refs/tags/v1.7.9-rc0^{}
f59f511e26b4924b22c6966e79fe4f754bc81dc6 refs/tags/v1.7.9.2
0e2d57fd50f61e668be3180bc8f25991ea88aa8c refs/tags/v1.7.10-rc1^{}
121f71f0da1bc9a4e1e96be2c3e683191a82a354 refs/tags/v1.7.10.4^{}
26e5c5d09334d157bd04f794f16f6e338d50c752 refs/tags/v1.7.10.3^{}
[...]
cffb45719f60d6fc2cc98ead6af88a895c63c9ac refs/tags/v1.7.12.4
d8cf053dacb4f78920c112d10c7be21e4f5a5817 refs/tags/v1.7.12.2^{}
dcd07fb6262fd8bb9f531890df3986a8b719a0b5 refs/tags/v1.7.12-rc0
e15c16de396a1e1f42001b03cb885ce64eb4098e refs/tags/v1.7.12-rc2^{}
While still not correct, it's closer. If we exclude -rc and ^{}, and add an additional sort on the last sub-version number, we can probably get close enough for most needs:
git ls-remote --tags git://github.com/git/git.git |grep "1\.7\."|grep -v -|grep -v {| sort -n -t. -k3 -k4
23ed9debf17263ed6bed478a4d6d86e71342c18a refs/tags/v1.7.11.6
527b331100ddba839cc54bb31c1bcd66acc08321 refs/tags/v1.7.11.7
14d20a75e3d57a872a8c81ae90dcc4c61ddba011 refs/tags/v1.7.12
51993a414a76120fda20d56ba767fa513d9ff440 refs/tags/v1.7.12.1
04043f4d1ae42bddee67d354a2e6fd2464592a1e refs/tags/v1.7.12.2
b38da673be332933b8f3a873ce46ffea08d2ee2c refs/tags/v1.7.12.3
cffb45719f60d6fc2cc98ead6af88a895c63c9ac refs/tags/v1.7.12.4
On
git ls-remote --tags "#{github_repo}" | awk '{print $2}' | grep -v '{}' | awk -F"/" '{print $3}' | sort -n -t. -k1,1 -k2,2 -k3,3 | tail -n 1.chomp
This worked for me how to get latest tag from github remote repository
On
Here is my one-liner :-)
git ls-remote --tags --refs --sort="version:refname" git://github.com/git/git.git | awk -F/ 'END{print$NF}'
On
Since version 2.18 git has a built-in --sort option for the exact purpose of sorting ref names.
So the up-to-date command would be
git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1
To also remove the hash and the dereference marker (^{}), just throw in some simple sed
git ls-remote --tags --sort="v:refname" git://github.com/git/git.git | tail -n1 | sed 's/.*\///; s/\^{}//'
As per suggestion by @Frederik Nord, you can also use the --refs switch to get rid of the ^{}, which leaves just one sed command (making the oneliner 4 characters shorter):
git ls-remote --tags --refs --sort="v:refname" git://github.com/git/git.git | tail -n1 | sed 's/.*\///'
# output: v2.18.0
For git versions prior to 2.18 here's a combo for piping output through sort
git ls-remote --tags git://github.com/git/git.git | sort -t '/' -k 3 -V | awk -F/ '{ print $3 }' | awk '!/\^\{\}/' | tail -n 1
On
% git -c 'versionsort.suffix=-' ls-remote -t --exit-code --refs --sort=-v:refname \
https://github.com/robert7/nixnote2 'v*' \
| sed -En '1!q;s/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/gp'
v2.1.0-beta4g
Pass --refs to git ls-remote to get rid of the {} refs shown in other answers:
$ git ls-remote -t --refs <URL>
This gives output such as:
8f235769a2853c415f811b19cd5effc47cc89433 refs/tags/continuous
24e666ed73486a2ac65f09a1479e91e6ae4a1bbe refs/tags/continuous-develop
7c2cff2c26c1c2ad4b4023a975cd2365751ec97d refs/tags/v2.0
35b69eed46e5b163927c78497983355ff6a5dc6b refs/tags/v2.0-beta10
To get only the tag names, pass through:
sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g':
$ git ls-remote -t --exit-code --refs https://github.com/robert7/nixnote2.git \
| sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g'
continuous
continuous-develop
v2.0
v2.0-beta10
You can then pass the cleaned up list through an appropriate grep and/or head -n1 (or add to your sed command if you like keeping your PID numbers low.)
Suggestions:
'v*' if all version tags start with a v.--exit-code to ensure a non-0 exit when no matching refs are returned.https:// version: it's faster and if you're packaging you don't want to run the risk of being asked for a ssh key.--sort=-v:refname to sort by version rather than lexographically, and have the largest versions at the topgit -c versionsort.suffix=- to prevent 2.0-rc coming "after" 2.0
On
For Git < 2.0 ls-remote --sort is not supported:
usage: git ls-remote [--heads] [--tags] [-u | --upload-pack ] [-q|--quiet] [--exit-code] [--get-url] [ [...]]
To list latest tags, with older Git releases as well, use the built-in sort command.
Printing tags, sorted by by version numbers (reversed) of the second column:
git ls-remote --tags $my_repo | sort -Vr -k2
...hash id... refs/tags/v0.10.0-rc0
...hash id... refs/tags/v0.9.0-rc0
...hash id... refs/tags/v0.9.0
...hash id... refs/tags/v0.8.1
...hash id... refs/tags/v0.8.0-rc1
Use grep to get the latest tag of a specific version (for example, latest 0.8 version):
git ls-remote --tags $my_repo | sort -Vr -k2 | grep -Po -m 1 "tags/\K.*0.8.*"
v0.8.1
TL;DR
With
git ls-remoteyou can get a list of references from a remote repository.To see what the latest version is, look at the last line of output from:
To only output the latest tag (for instance in a shell script) of a repository that uses Semantic Versioning use:
For older versions of Git that don't have the
--sortflag (pre v2.18), or versions that don't supportversionsort.suffix(pre v2.4) use:Older versions of
sortthat don't have the--version-sortflag are out of scope for this question...The long version
Tags only
Using
--tagsmakes sure the list only contains tag references.This will include both referenced and de-referenced tags. That means some tags will have
^{}at the end of the refname. (For more information about that see this question elsewhere on StackOverflow.)For human consumption this doesn't matter much, but if you don't want to see those
^{}'s add--refs.Sorting
It is possible sort the list of references using
--sort.The sort option uses the same sort keys as
git for-each-ref. As we don't have all of the information locally, not all of the options are available to us (for instance date related sort keys).We want to use version sort, based on the reference name. To do so, we use the
version:refnamekey. This can also be abbreviated tov:refname.This will sort the versions ascending, meaning the latest version will be last.
To reverse the list prepend the sort key with
-:--sort='-v:refname'.Pre-release sorting
At this point, version-sort will place release candidates (for instance
v2.28.0-rc2) after the stable version that they should come in front of.Since v2.12 we can use a configuration flag that tells Git to sort refnames with a specific character suffix after references without that character suffix:
git -c 'versionsort.suffix=-'.To always use
versionsort.suffixlike this, it can be set globally:Between v2.4 and v2.12 the flag is called
versionsort.prereleaseSuffix.Sorting in older versions of Git
For older Git versions a trick can be used: a dash character
-is sorted before a spacebut a tilde~is sorted after a space.So by replacing the dash
-with a tilde~, things get sorted in the right order. This can be done usingtr '-' '~'One line only
As we don't really care for all of the output, other than the last line, we only show the tail:
tail --lines=1. Of course, if the list is retrieved in descending order (with--sort='-v:refname'), this would be:head --lines=1.Just the Refname
The output from the ls-remote command also outputs the reference hash:
To only see the actual tag (i.e. the reference name), we can cut of the first part of the line:
cut --delimiter='/' --fields=3Reference filter
The last thing to note is that ls-remote can be given a filter to only show reference that match the filter pattern. For instance, for Semantic Versioning we could use:
'*.*.*'. Anything that does not match that pattern will not be shown.If the repository always prefixes a version tag with a
v, it could be narrowed down further to'v*.*.*'.Another example is to only retrieve the latest tag for a specific main version. For instance, to only see tags for verion 2 of a repo, we could use
'v2.*'.Make sure to use quotes around the filter, otherwise that star
*will cause you trouble!Reference not found
When using a filter it is a good idea to use the
--exit-codeflag.This is because Git will always exit with status code
0to indicate it successfully talked with the remote repository.For human consumption this is fine, as you'll see on the screen if any refs have been found.
If this code is used in a shell script, however, that can be problematic.
Git can be told to use status code
2when no matching refs are found in the remote repository. This is done by using the--exit-codeflag.That way a script will know when something goes wrong!
Obviosuly, if no filter is used, using
--exit-codedoes not really make sense.Time for an example!
Lets say we wanted to know what the latest tag of Git is.
We would do:
That would return a long list with all the tags in order, as shown below (truncated for sanity's sake).
This tells us the latest tag is
v2.28.0.Another example would be to set
versionsort.suffixglobally and then get just the last tag:Now, let's see if there is already a version 3 of Git!