Shell脚本 - 尝试验证if/else语句中git存储库中是否存在git标记

Kim*_*im 41 git bash shell

我正在为zend应用程序创建一个部署脚本.几乎只完成了脚本我想验证repo中是否存在标记以强制团队中的标记.目前我有以下代码:

# Fist 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
Run Code Online (Sandbox Code Playgroud)

期待您的反馈!

更新

当我在命令行中执行以下命令时:

cd /git/repo/path && git rev-list v1.4..
Run Code Online (Sandbox Code Playgroud)

没有输出,这很好.虽然我执行时:

cd /git/repo/path && git rev-list **BLA**..
Run Code Online (Sandbox Code Playgroud)

我收到一个错误,这也很好:

fatal: ambiguous argument 'BLA..': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
Run Code Online (Sandbox Code Playgroud)

语句中的-z表示,如果sting为空,那么...换句话说,它通过命令行工作正常.虽然当我在语句中的shell脚本中使用相同的命令时,它似乎不起作用.

[ -z "'cd /git/repo/path && git rev-list $1..'" ]
Run Code Online (Sandbox Code Playgroud)

这个方法的灵感来自Validate if commit是否存在

更新2

我发现了问题:

请参阅在shell脚本中使用if if if if >

sh将&&解释为shell运算符.将它更改为-a,这是[的连接操作符:

["$ arg1"="$ arg2"-a"$ arg1"!="$ arg3"]此外,你应该总是引用变量,因为[当你放弃参数时会感到困惑.

换句话说,我改变了&&;并简化了条件.现在它很漂亮.

if cd /path/to/repo ; git rev-list $1.. >/dev/null

then

    echo "gogo"

else
    echo "WRONG"
    exit
fi
Run Code Online (Sandbox Code Playgroud)

Joh*_*ter 41

你可以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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

您也可以使用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
Run Code Online (Sandbox Code Playgroud)

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


lxg*_*lxg 35

这是cad106uk解决方案的更简单版本:

version=1.2.3

if [ $(git tag -l "$version") ]; then
    echo yes
else
    echo no
fi
Run Code Online (Sandbox Code Playgroud)

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

注意:周围的引号$version对于避免误报非常重要.因为if由于$version某种原因是空的,所以git tag -l只列出所有标签,条件总是为真.

  • 是的,也是这样:) (2认同)

Las*_*ssi 19

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

tag=whatever
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
    echo "found"
else
    echo "not found"
fi
Run Code Online (Sandbox Code Playgroud)

看起来很健壮:

  • 检查标记,而不检查分支或提交哈希等.
  • 奇怪的标签名称输入不会导致奇怪的行为:
    • 以" - "开头的标记名称不会被误认为是命令行选项
    • 包含斜杠或点的标记名称并不特殊
    • 包含空格的标记名称并不特殊
    • 空白标签名称并不特殊

  • 不幸的是,如果$ tag字符串以"-q"结尾,并且字符串包含7个或更多十六进制数字(例如在`git describe`中生成的"long"标签中),这将在提交哈希上匹配,即使有没有这样的标签.使用`git tag --list`或`git show-ref --tags`的grep选项是我发现的唯一避免这种情况的选项. (3认同)

小智 6

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

TAG_NAME=$1
git ls-remote --exit-code --tags origin $TAG_NAME || echo 'not found'
Run Code Online (Sandbox Code Playgroud)


cad*_*6uk 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
Run Code Online (Sandbox Code Playgroud)