Shell - check if a git tag exists in an if/else statement
bash, git, shell
Solution
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.
Problem
I am creating a deploy script for a zend application. The script is almost done only I want to verify that a tag exists within the repo to force tags on the team. Currently I have the following code: ``` # First update the repo to make sure all the tags are in cd /git/repo/path git pull # Check if the tag exists in the rev-list. # If it exists output should be zero, # else an error will be shown which will go to the else statement. if [ -z "'cd /git/repo/path && git rev-list $1..'" ]; then echo "gogo" else echo "No or no correct GIT tag found" exit fi ``` Looking forward to your feedback! Update When I execute the following in the command line: ``` cd /git/repo/path && git rev-list v1.4.. ``` I get NO output, which is good. Though when I execute: ``` cd /git/repo/path && git rev-list **BLA**.. ``` I get an error, which again is good: ``` fatal: ambiguous argument 'BLA..': unknown revision or path not in the working tree. Use '--' to separate paths from revisions ``` The -z in the statement says, if sting is empty then... In other words, it works fine via command line. Though when I use the same command in a shell script inside a statement it does not seem to work. ``` [ -z "'cd /git/repo/path && git rev-list $1..'" ] ``` This method is inspired by Validate if commit exists Update 2 I found the problem: See Using if elif fi in shell scripts > sh is interpreting the && as a shell operator. Change it to -a, that’s [’s conjunction operator: [ "$arg1" = "$arg2" -a "$arg1" != "$arg3" ] Also, you should always quote the variables, because [ gets confused when you leave off arguments. in other words, I changed the `&&` to `;` and simplified the condition. Now it works beautiful. ``` if cd /path/to/repo ; git rev-list $1.. >/dev/null then echo "gogo" else echo "WRONG" exit fi ```