使用 git rev-parse <tag> 的错误提交哈希

Wrong Commit Hash with git rev-parse <tag>

我现在 git 有一些奇怪的行为。

我有一个代码库,其中有一个标记为 v2.3.0

的提交

如果我 运行 git log,我可以看到我最新的提交哈希是:

commit b2ee576083607b7ba451b72642a77ca3309e4ac9 (HEAD, tag: v2.3.0, origin/staging, origin/master, origin/develop, origin/HEAD, master)
Author: B <b@b.com>
Date:   Thu Apr 1 16:53:48 2021 +0000

酷!这与我在 git 回购中看到的一致

如果我运行 git checkout v2.3.0,我也会得到相同的提交散列。甜

但是,如果我 运行 git rev-parse v2.3.0,要查看哪个提交哈希与我的标签对齐,我会得到提交哈希 85607530aa64da4df34e7160d073df5c2699439b...???

如果我随后尝试检查该提交哈希,我的代码库仍会说它位于 b2ee576083607b7ba451b72642a77ca3309e4ac9(即它没有改变)

据我所知,我有一个奇怪的幻象提交哈希,它在我的 git 存储库中找不到,但它似乎指向我的实际提交哈希。这给我带来了问题,因为我有一个脚本依赖于 git rev-parse.

的正确输出

我有 git 版本 git version 2.25.1

有人知道这里发生了什么吗?

有两种标签。一个是普通标签,一个是注释标签。普通的只是像分支一样的引用,而带注释的是像提交一样的对象。

git rev-parse a_normal_tag returns 标签引用的对象的哈希值。在大多数情况下,这个引用的对象是一个提交。在极少数情况下,它还可以指向标记对象、blob 对象或树对象。

git rev-parse an_annotated_tag returns 标签本身对象的哈希。

如果您想获取引用提交的哈希值而不考虑标记类型,请使用 git rev-parse some_tag^{}。正如 doc 所说,^{} 用于递归取消引用标签,直到找到非标签对象。

这不是 提交 哈希。那是 注释标签 v2.3.0 的哈希 ID。带注释的标签本身就是对象,因此它们有自己的哈希 ID。像名称(例如分支和标签名称)一样,它们依次指向其他一些对象——通常直接指向提交。

git rev-parse 将任何标签变成它可能指向的最终对象,请使用 ^{} 后缀,这意味着 如果这是一个标签对象,则跟随它到达目的地,如果那是另一个标签,请继续关注。如果您提供的名称可能指向 commit 对象以外的其他对象——例如,指向树或 blob 对象——并且您希望确保它确实指向 commit,使用^{commit}后缀:

git rev-parse v2.3.0^{commit}

如果标记指向提交以外的任何内容,这将产生错误(非零退出状态),因此请检查。