65

I am creating a deploy script for a zend application. The scrip 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 what 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
4

7 回答 7

85

为什么这么复杂?这是一个非常简单的解决方案(基于页面下方的 cad106uk 方法):

version=1.2.3

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

没有必要将 的输出git tag -l与版本号进行比较,因为如果找不到版本,则输出将为空。因此,测试是否有任何输出就足够了。

注意:周围的引号$version对于避免误报很重要。因为如果$version出于某种原因为空,git tag -l只会列出所有标签,并且条件始终为真。

于 2017-04-01T11:20:39.240 回答
57

您可以git rev-parse改用:

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调用图形行走,哪里git rev-parse可以避免它。上面有一些可能查找对象而不是标签的问题。您可以通过使用^{tag}标签名称来避免这种情况,但这仅适用于带注释的标签,不适用于轻量级标签:

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 还指出,如果您的标签名称以 a 开头-,那么它可能会被解释为一个选项。你可以通过寻找来避免这个问题refs/tags/$1。因此,总而言之,使用该rev-parse版本,您可以查找refs/tags/$1获得轻量级和带注释的标签,并且可以^{tag}在末尾附加 a 以强制使用带注释的标签 ( refs/tags/$1^{tag})。

此外,正如@forvaidya 之前提到的,您可以简单地列出您想要的标签和 grep:

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

您也可以使用git tag --list代替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

如果您知道标签,我认为最好只是通过rev-parse. 我不喜欢该egrep版本的一件事是,您可能拥有可能被解释为正则表达式序列并导致误报或误报的字符。该rev-parse版本在这个意义上是优越的,因为它不会查看整个标签列表。

另一种选择是使用的模式特征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

这避免了额外的egrep调用并且更直接。

于 2013-07-22T16:51:43.863 回答
20

这是进一步开发的rev-parse版本:

tag=whatever
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
    echo "found"
else
    echo "not found"
fi

它似乎很健壮:

  • 仅检查tag,而不是分支或提交哈希等。
  • 奇怪的标签名称输入不会导致奇怪的行为:
    • 以“-”开头的标记名称不会被误认为是命令行选项
    • 包含斜线或点的标签名称并不特殊
    • 包含空格的标签名称并不特殊
    • 空白标签名称并不特殊
于 2016-04-29T15:46:30.567 回答
8

非常简单的版本(使用 git ls-remote)

TAG_NAME=$1
git ls-remote --exit-code --tags origin $TAG_NAME || echo 'not found'
于 2018-08-03T05:51:43.037 回答
5

我认为我非常喜欢的解决方案是使用更现代的 git 版本(git 版本 2.7.4)

#!/usr/bin/env bash
cd /to/repo/base;
tagName="Whatever";

if [[ `git tag -l $tagName` == $tagName ]]; then
    echo "yes";
else
    echo "no";
fi
于 2016-11-03T15:18:38.347 回答
3

假设您在项目根目录中...

# Filename: check-for-tag
# Usage:    check-for-tag <TAG_NAME>
# Example:  check-for-tag ticket-123-fix-this-bug
TAG_NAME=$1
git ls-remote --tags 2>/dev/null | grep $TAG_NAME 1>/dev/null
if [ "$?" == 0 ]; then 
   echo "Git tag $TAG_NAME exists."
else  
   echo "Git tag $TAG_NAME does not exist."
fi
于 2016-04-21T14:41:44.797 回答
0

我使用这种方法来判断当前版本是否存在标记,以避免标记两次。

git_rev_id=$(git -C $REPO_FOLDER rev-parse HEAD)
git_tags=$(git tag)

for git_tag in $git_tags; do
    git_temp_tag=$(git cat-file tag $git_tag | grep $git_rev_id);
    if [ -z "$git_temp_tag" ]
    then
        false; #do nothing
    else
        git_tag_exists=$git_tag
    fi
done

if [ -z "$git_tag_exists" ]
then
  echo "need to make a tag"
else
  echo "Found tag: $git_tag_exits"
fi
于 2018-07-26T17:22:50.700 回答