错误的日期进入预接收挂钩
Posted
技术标签:
【中文标题】错误的日期进入预接收挂钩【英文标题】:Wrong date come in pre-receive hook 【发布时间】:2018-05-29 10:28:27 【问题描述】:我尝试使用 git 命令查找工作分支名称。当然,我可以在本地(Windows)机器上获得正确的分支名称。如果我在预接收挂钩文件中使用相同的命令意味着它只打印master
。但是在本地,我得到了我工作的分支名称。
我用来获取分支的命令是
#!/usr/bin/env bash
echo `git rev-parse --abbrev-ref HEAD`
echo `git symbolic-ref --short HEAD`
echo `git branch | sed -n '/\* /s///p'`
echo `git status | head -1`
echo `git describe --all`
真是莫名其妙!任何人都建议一种在 git hook 文件中获取工作分支名称的正确方法(pre-receive
hook)
【问题讨论】:
【参考方案1】: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
参数。
【讨论】:
git symbolic-ref --short HEAD
我在钩子上使用了同一行。实际上,我在我的test
分支中提交我的更改并在本地(Windows)中提交,所以test
是我的工作分支!我对吗?现在将更改推送到原点,在挂钩中 echo `git symbolic-ref --short HEAD`
打印 master
而不是 test
当然:test
是你的工作分支。它不是 other Git 的工作分支。 这里涉及两个不同的 Git 存储库。
还有其他方法可以在钩子中找到test
分支吗?
your 存储库中的当前分支与不是 you 的人无关。接收端 Git 可以通过读取标准输入找到您(或发送端 Git)请求更新的名称,正如我所展示的。以上是关于错误的日期进入预接收挂钩的主要内容,如果未能解决你的问题,请参考以下文章
尝试将现有 git 项目上传到 gitlab 时如何解决“预接收挂钩被拒绝”错误?