How to get last Git tag matching regex criteria

RegexGitTagsFindTagging

Regex Problem Overview


I need Git command to get/find last tag starting with 'v' to get last versioning commit (I am using tags with v letter at the beginning to tag next application version (example: v0.9.1beta).

Is there any way to do it?

Regex Solutions


Solution 1 - Regex

I'm using the following command for this:

git describe --match "v[0-9]*" --abbrev=4 HEAD

It will also modify the version if you did something with the source tree since your last versioned tag.

Please note that this is not a regex but a glob but works for the provided example.

Solution 2 - Regex

git tag -l -n v*

Solution 3 - Regex

The problem with using git describe as the other answers do is that git describe will show you tags that are reachable from HEAD (or the commit you specify.)

Imagine you have 3 tags, v1, v2, and v3. If HEAD is at a point between v2 and v3, git describe would return v2 rather than v3.

If you actually want the latest tag, first of all you need annotated tags as lightweight tags have no date metadata.

Then this command will do it:

git for-each-ref --sort=-taggerdate --count=1 refs/tags/v*

Solution 4 - Regex

Also with git describe you could get the latest tag not just reachable from HEAD with :

git describe --match "v*" --abbrev=0 --tags $(git rev-list --tags --max-count=1)

Solution 5 - Regex

KARASZI István's answer already explains how to find tags matching a glob, which is usually fine enough. Should you ever need a real RegEx though:

for tag in $(git tag | grep YOURREGEX); do
    git describe --tags --long --match="$tag" 2>/dev/null
done | sort -k2 -t"-" | head -n1
  • If you only want the nearest tag (i.e. what --abrev=0 would achieve), append | cut -d"-" -f1
  • If you don't want --long's behaviour of also outputting an exactly matching tag including the -0-hash part, append | sed -e's/-0-.*$//' instead.

The question's example tag would probably use a Regex ^v\d+\.\d+\.\d+\D*$ (though the \D*$ might be optional).

Solution 6 - Regex

While a single regex --match "v[0-9]*" is enough here, know that Git 2.13 (Q2 2017) will improve that:

> "git describe" and "git name-rev" have been taught to take more than one refname patterns to restrict the set of refs to base their naming output on, and also learned to take negative patterns to name refs not to be used for naming via their "--exclude" option.

See commit 77d21f2, commit 43f8080, commit 96415b4, commit 290be66, commit 4a68748 (18 Jan 2017) by Jacob Keller (jacob-keller).
(Merged by Junio C Hamano -- gitster -- in commit 1b32498, 27 Feb 2017)

You now can have multiple match pattern:

--match <pattern>:

> Only consider tags matching the given glob(7) pattern, excluding the "refs/tags/" prefix.
This can be used to avoid leaking private tags from the repository.

> If given multiple times, a list of patterns will be accumulated, and tags matching any of the patterns will be considered.
Use --no-match to clear and reset the list of patterns.

And you have also an exclude pattern (or several) now!

--exclude <pattern>::

> Do not consider tags matching the given glob(7) pattern, excluding the "refs/tags/" prefix.

> This can be used to narrow the tag space and find only tags matching some meaningful criteria.
If given multiple times, a list of patterns will be accumulated and tags matching any of the patterns will be excluded.
When combined with --match a tag will be considered when it matches at least one --match pattern and does not match any of the --exclude patterns.
Use --no-exclude to clear and reset the list of patterns.

Solution 7 - Regex

git describe --match v*

Use this.

Solution 8 - Regex

I use

git tag -l --format "%(objecttype) %(refname:short)" --sort=-version:refname --merged HEAD "v*"

git tag interprets the pattern as glob. So you cannot specify a full blown regex. Just use a minimal glob (v*) or even no glob at all. You will receive more than only one matching tag in sorted order (highest tag version first) and you will be able to regex the output afterwards.

Solution 9 - Regex

Something more complex would be along the lines of:

/v[0-9]+(\.[0-9]+).*/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLukaszView Question on Stackoverflow
Solution 1 - RegexKARASZI IstvánView Answer on Stackoverflow
Solution 2 - RegexracerrorView Answer on Stackoverflow
Solution 3 - RegexJoe AlcornView Answer on Stackoverflow
Solution 4 - RegexBarthelemy PavyView Answer on Stackoverflow
Solution 5 - RegexTobias KienzlerView Answer on Stackoverflow
Solution 6 - RegexVonCView Answer on Stackoverflow
Solution 7 - RegexLukaszView Answer on Stackoverflow
Solution 8 - RegexHenningView Answer on Stackoverflow
Solution 9 - RegexOtieno RowlandView Answer on Stackoverflow