如何从带注释的标签中获取附加提交的哈希值

时间:2019-01-22 22:37:37

标签: bash git githooks

我想做的是创建一个预推钩子,该钩子需要一个标签指向与当前HEAD相同的提交。我们以一种不寻常的方式使用git,在任何情况下,最新的提交都不应该带有标签。我对此有一个有效的实现,但发现它仅适用于轻量级标签。

head=$(git rev-parse HEAD)
last_tag=$(git rev-parse $(git describe --tags))
if [ "$head" != "$last_tag" ]
then
    echo >&2 'Aborting push - there is no tag on the latest commit.'
    exit 1
fi

我发现的问题是,即使在设置push.followTags之后,轻量级标签也会被忽略。对我来说很重要的一点是,无需额外的步骤即可推拉标签,因为我们将大量使用它们。

要变通解决此问题,我们可以使用带注释的标签。问题是带注释的标记具有它自己的哈希,由git rev-parse返回。我无法找到一种方法来获取标签链接到的提交的哈希值。我都尝试过

git rev-parse tagname^
git rev-parse $(git rev-parse tagname)^

有什么想法可以做到这一点,或者还有其他更好的选择吗?

1 个答案:

答案 0 :(得分:1)

我将以重复的形式将其关闭,但是接受重复的 at 不一定是最好的方法。

最好的方法是使用git rev-parse tagname^{}git rev-parse tagname^{commit}

这两者之间的主要区别在于,前者将标签跟随到某个非标签对象(可能是提交,但可能是树或斑点),而后者则将标签跟随到一个提交。如果该标记未指向(直接或间接)提交,则第二种形式将生成错误消息(发送至stderr)和非零状态:

hash=$(git rev-parse ${tag}^{commit}) || exit

或者,如果您不介意$tag是否命名树或Blob对象:

hash=$(git rev-parse ${tag}^{}) || exit

在给定指向树或斑点的标签时,git log方法将不会产生任何输出(并成功退出):

$ git tag -a foo -m test HEAD^{tree}
$ git log foo
$ git rev-parse foo
98769d20d108a98555aafab76b0e3b84a3719779
$ git rev-parse foo^{}
f7a4925fb621cdef69d7dec49159c13cfc6aa789
$ git rev-parse foo^{commit}
error: foo^{commit}: expected commit type, but the object dereferences to tree type
foo^{commit}
error: foo^{commit}: expected commit type, but the object dereferences to tree type
fatal: ambiguous argument 'foo^{commit}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ $ git tag -d foo
Deleted tag 'foo' (was 98769d20d1)

通过使用^{}^{commit}表示法,您可以选择所需的行为。