在使用 git 的时候大部分时候都是通过 git rev-parse <branch-name> 来获取某个分支名对应的 commit id 但是一直没遇到通过 commit id 来获取分支名的场景。在学习 git rebase 命令的时候突然想知道有没有这个命令。于是就开始问 chatgpt 了。

最开始,我问 chatgpt

git rev-pase <branch-name> 这个命令可以根据分支名获取对应的commit id,有没有相反的命令:根据commit id获取对应的分支名?

chatgpt 跟我说:

可以通过 git branch --contains <commit-id> 这个命令来实现。

很明显这个命令不是我想要的,我需要是精确匹配,也就是 branch-name 通过 git rev-parse 解析后,刚好等于我指定的 commit-id 。于是我纠正 chatgpt ,让它给我提供一个可以精确匹配的方案。

于是 chatgpt 又给出了一个解决方案:

git show-ref | grep <commit-id>

这个方案确实可以满足我的需求,但是我总觉得不是最优解。于是我继问:

你上面的命是可以实现的。但有没有更高效的命令,像git rev-parse一样直接获取。而不是需要我自己去grep

接着 chatgpt 又给出一个解决方案:

git name-rev --name-only <commit-id>

如果这个 commit id 正好对应某个分支的最新 commit,这个命令会返回对应的分支名。

然而,git name-rev 会尝试找到最接近的引用(分支或标签)来命名 commit,因此如果 commit 不正好是某个分支的 HEAD,返回的结果可能会是一个基于最接近引用的名称(例如 master~2 表示 master 分支倒数第二个 commit)。 如果你需要更加精确地确定某个 commit id 是否正好对应于某个分支的 HEAD,可以使用以下命令:

git for-each-ref --format='%(refname)' refs/heads/ | while read ref; do if [ "$(git rev-parse $ref)" = "<commit-id>" ]; then echo $ref fi done

很明显,这个方案越来越复杂了,还不如最开始的 git show-ref | grep <commit-id> 简洁。然后我又追问 chatgpt

脚本太复杂了,就没有更简洁的命令吗?

最后 chatgpt 终于给出了我满意的答案:

确实可以简化查询是否有分支的 HEAD 完全匹配指定的 commit ID。以下是一个更简洁的命令:

git branch --points-at <commit-id>

这个命令会列出所有分支,它们的 HEAD 完全匹配指定的 commit ID。

假设你的 commit ID 是 abc123,你可以运行以下命令:

git branch --points-at abc123

这将列出所有 HEAD 指向 abc123 的分支。这样,你就可以直接找到那些分支的 HEAD 完全匹配特定的 commit ID,而不需要编写复杂的脚本。

最后,我查了一下,git branch --points-at 替换成 git tag --points-at 就可以处理 tag 相关的查询了。