错误的日期进入预接收挂钩

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

说明

我并不完全清楚您所说的“工作分支名称”是什么意思。但是,确实所有存储库都有HEADgit 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 &lt;branch-or-tag&gt;,但如果其他人这样做't-b &lt;branch-or-tag&gt;,其他人的 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 时如何解决“预接收挂钩被拒绝”错误?

GitHub:预接收挂钩

检查 GitHub 预接收挂钩的作用

git,Heroku:预接收挂钩被拒绝

尝试接收条带挂钩时在 Django 上获取 MultiValueDictKeyError

后置接收挂钩