在使用 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
相关的查询了。