TL;DR:我认为您误解了预接收挂钩的角色以及运行预接收挂钩的存储库的HEAD。
说明
我并不完全清楚您所说的“工作分支名称”是什么意思。但是,确实所有存储库都有HEAD,git symbolic-ref --short HEAD 将打印HEAD 指向的分支的名称(“当前分支”),即使该分支还不存在;如果它不指向分支名称(即,是分离的 HEAD),则失败。
即:
$ mkdir tt
$ cd tt
$ git init
Initialized empty Git repository in .../tt/.git
$ git symbolic-ref --short HEAD
master
即使:
$ git branch
(注意没有输出)
$ git rev-parse HEAD
HEAD
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
(git rev-parse HEAD 失败)
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
(当前分支是master,但没有提交)。
所以git symbolic-ref --short HEAD 可能是您正在考虑的事情。 (请注意,在新的--bare 存储库中,以上所有内容都将继续工作或失败,但git status 除外,它会显示fatal: This operation must be run in a work tree。)
这没什么意义的主要原因是您还提到了预接收挂钩,并且预接收挂钩主要在接收和接受推送请求的集中式服务器“裸”存储库中有用。请记住,裸存储库是没有工作树的存储库。在一个裸仓库中,HEAD 指向的分支的名称几乎完全没用。它有一个实际功能:如果运行git clone 的人没有指定要签出的特定名称,它会确定该存储库的git clone 将签出哪个分支。1 在正常情况下,非裸存储库,HEAD 将是填充该非裸存储库的工作树的分支的名称;但由于裸存储库没有工作树,HEAD 没有这样的事情。
但是,一般来说,预接收钩子无论如何都没有咨询 current 分支的业务。预接收钩子运行时,其标准输入连接到将提供一条或多行输入的流。每一行的格式如下:
old-hash new-hash reference-name
例如,
3b136a71d875174d7539bf98080b85eaf415ba73 95ec6b1b3393eb6e26da40c565520a8db9796e9f refs/heads/foobranch
0000000000000000000000000000000000000000 0452b4b5786778d5d87f5c90a94fab8936502e20 refs/tags/v2.1.0
在这种情况下,表示发送 Git 希望接收 Git 将分支 foobranch 从其当前值 3b136a71d875174d7539bf98080b85eaf415ba73 更新为新值 95ec6b1b3393eb6e26da40c565520a8db9796e9f,并创建指向对象 @ 的标记 v2.1.0 987654346@.
这一切都不依赖于当前分支。这些更新请求由执行git push 的 Git 提供。由于接收存储库是(大概,尽管您可以检查是否愿意)--bare,它没有工作树,因此创建标签或替换 foobranch 的值不会影响不存在的工作-任何方式的树。
1也就是说,当其他人克隆这个裸存储库时,其他人可以说-b <branch-or-tag>,但如果其他人这样做't 说 -b <branch-or-tag>,其他人的 Git 会询问裸存储库 Git 它的 HEAD 代表什么分支,然后像其他人指定的那样进行设置 作为-b 参数。