【问题标题】:Shell - check if a git tag exists in an if/else statementShell - 检查 if/else 语句中是否存在 git 标签
【发布时间】:2013-07-21 08:07:15
【问题描述】:

我正在为一个 zend 应用程序创建一个部署脚本。脚本几乎完成了,只是我想验证存储库中是否存在标签以强制团队添加标签。目前我有以下代码:

# 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

期待您的反馈!

更新

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

cd /git/repo/path && git rev-list v1.4..

我得到 NO 输出,这很好。虽然当我执行时:

cd /git/repo/path && git rev-list **BLA**..

我得到一个错误,这又是好事:

fatal: ambiguous argument 'BLA..': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

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

[ -z "'cd /git/repo/path && git rev-list $1..'" ]

这个方法灵感来自Validate if commit exists

更新 2

我发现了问题:

Using if elif fi in shell scripts >

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

【问题讨论】:

标签: git bash shell


【解决方案1】:

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

version=1.2.3

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

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

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

【讨论】:

  • 是的,它也是:)
【解决方案2】:

您可以改用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 还指出,如果您的标签名称以 - 开头,那么它可能会被解释为一个选项。您可以通过查找 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

您也可以使用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 调用,并且更直接。

【讨论】:

  • 是的,定义 GIT_DIR 是个好方法!我认为他们都工作。还是谢谢。
  • rev-parse 选项将匹配 Git “长”标签(由 git describe 生成),但第二个选项仅匹配真实标签。谢谢!不过,我认为使用git show-ref --tags 比使用git tag --list 没有任何优势。有关系吗?
  • @big_m 没关系。你只需要确保正确匹配它......所以使用类似egrep -q "^$1$"的东西来匹配确保你匹配整个条目。
  • @big_m 我用一个额外的块更新了答案,展示了如何使用rev-parse 版本只查找标签。
  • 感谢^{tag} 后缀提示,@jszakmeister!我可以发誓我试过了,但显然没有(或者无论如何都不正确)。我刚刚又试了一次,果然如你所说。
【解决方案3】:

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

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

它看起来很健壮:

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

【讨论】:

  • 不幸的是,如果 $tag 字符串以“-q”和 7 个或更多十六进制数字的字符串结尾(例如在从 git describe 生成的“long”标签中),这将匹配提交哈希,即使没有这样的标签。 git tag --listgit show-ref --tags 的 grep 选项是我发现的唯一可以避免这种情况的选项。
【解决方案4】:

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

TAG_NAME=$1
git ls-remote --exit-code --tags origin $TAG_NAME || echo 'not found'

【讨论】:

    【解决方案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
    

    【讨论】:

      【解决方案6】:

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

      # 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
      

      【讨论】:

      • 如果你想知道确切的标签是否存在,你可以运行git ls-remote --tags 2&gt;/dev/null | grep "refs/tags/$TAG_NAME$" 1&gt;/dev/null
      【解决方案7】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-04
        • 1970-01-01
        • 2014-10-24
        • 1970-01-01
        • 1970-01-01
        • 2013-04-15
        • 2013-10-02
        • 1970-01-01
        相关资源
        最近更新 更多