Shell - check if a git tag exists in an if/else statement

Why so complicated? Here’s a dead-simple solution (based on cad106uk’s approach further down the page):

version=1.2.3

if [ $(git tag -l "$version") ]; then
    echo yes
else
    echo no
fi

It is not necessary to compare the output of git tag -l with the version number, because the output will be empty if the version is not found. Therefore it’s sufficient to test if there’s any output at all.

Note: The quotes around $version are important to avoid false positives. Because if $version is empty for some reason, git tag -l would just list all tags, and the condition would always be true.


You could use git rev-parse instead:

if GIT_DIR=/path/to/repo/.git git rev-parse $1 >/dev/null 2>&1
then
    echo "Found tag"
else
    echo "Tag not found"
fi

git rev-list invokes graph walking, where git rev-parse would avoid it. The above has some issues with possibly looking up an object instead of a tag. You can avoid that by using ^{tag} following the tag name, but this only works for annotated tags and not lightweight tags:

if GIT_DIR=/path/to/repo/.git git rev-parse "$1^{tag}" >/dev/null 2>&1
then
    echo "Found tag"
else
    echo "Tag not found"
fi

@Lassi also points out that if your tag name begins with a -, then it might get interpreted as an option instead. You can avoid that issue by looking for refs/tags/$1 instead. So in summary, with the rev-parse version, you can look for refs/tags/$1 to get both lightweight and annotated tags, and you can append a ^{tag} to the end to enforce an annotated tag (refs/tags/$1^{tag}).

Also, as mentioned before by @forvaidya, you could simply list the tags and grep for the one you want:

if GIT_DIR=/path/to/repo/.git git show-ref --tags | egrep -q "refs/tags/$1$"
then
    echo "Found tag"
else
    echo "Tag not found"
fi

You can also use git tag --list instead of git show-ref --tags:

if GIT_DIR=/path/to/repo/.git git tag --list | egrep -q "^$1$"
then
    echo "Found tag"
else
    echo "Tag not found"
fi

If you know the tag though, I think it's best just to just look it up via rev-parse. One thing I don't like about the egrep version is that it's possible you could have characters that could get interpreted as regex sequences and either cause a false positive or false negative. The rev-parse version is superior in that sense, and in that it doesn't look at the whole list of tags.

Another option is to use the pattern feature of git show-ref:

if GIT_DIR=/path/to/repo/.git git show-ref --tags "refs/tags/$1" >/dev/null 2>&1
then
    echo "Found tag"
else
    echo "Tag not found"
fi

This avoids the extra egrep invocation and is a bit more direct.