git 预接收挂钩无法为服务器上的其他存储库执行 git 命令

git pre-receive hook fails to execute git commands for other repository on server

我在本地 docker 上有一个 git 服务器,我在其中托管 2 个存储库:main.gitsub.gitsubmain 仓库中的一个子模块。他们俩都是光着身子的。我尝试向我的 main 回购添加一个预接收挂钩,检查我是否没有引用丢失的子模块修订(例如,如果有人忘记在推送主回购之前推送子模块)。我使用这个脚本:https://gist.github.com/T3sT3ro/902d67f29d2c913b3fef6034776777e0 which is a slightly fixed version of this one: https://gist.github.com/bagage/bdca3d4b66d43db7a5e3.

不幸的是,这个脚本不起作用。如果从 main 仓库的 pre-receive 钩子中启动,为 sub 仓库执行的任何 git 命令都会失败。当手动 运行 时,一切似乎都很好。例如执行 git log|show 导致 bad object HEADgit branchfatal: missing object 78f5da8ed1f83047d0f68fe17e5eaf86060038c3 for refs/heads/master,即使 运行ning git branch --contains 78f5da8ed1f83047d0f68fe17e5eaf86060038c3sub 回购正常工作:打印 * master.

运行ning git fsck 挂钩子回购(设置调试变量)returns this:

remote: 16:45:32.575940 trace.c:318             setup: git_dir: .
remote: 16:45:32.575961 trace.c:319             setup: git_common_dir: .
remote: 16:45:32.575967 trace.c:320             setup: worktree: (null)
remote: 16:45:32.575971 trace.c:321             setup: cwd: /var/www/git/sub.git
remote: 16:45:32.575976 trace.c:322             setup: prefix: (null)
remote: 16:45:32.575982 git.c:344               trace: built-in: git fsck
remote: error: HEAD: invalid sha1 pointer 78f5da8ed1f83047d0f68fe17e5eaf86060038c3
remote: error: refs/heads/master: invalid sha1 pointer 78f5da8ed1f83047d0f68fe17e5eaf86060038c3
remote: notice: No default references
remote: 16:45:32.580070 read-cache.c:1925       performance: 0.000004548 s: read cache ./index
remote: 16:45:32.580107 trace.c:420             performance: 0.004374272 s: git command: git fsck
remote: dangling commit 468626a3126e8139a08727ff3c1b25f37e23f957

我尝试将 hook 的所有者和组更改为与其他文件相同,但它不起作用。这有点像某种安全机制,但另一方面,我可以在 sub 存储库中 touch 文件。从上面的 fsck 日志中我们还可以看到 78f5da... 出现在某处...

repro 是这样的:创建 main 和 sub repo,将一些初始提交推送到两者,将 sub 作为子模块添加到 main,在 sub 上提交而不推送,在 main 中添加 sub(main 现在应该引用 sub 的本地提交回购),尝试推送主回购(失败 - 预期),推送子回购,尝试推送主回购(再次失败 - 现在出现这些错误)。

git 服务器版本:2.17.1

事实证明,git 设置了一些环境变量,为了允许 git 挂钩在其他一些 repo 上工作,我们需要取消设置一些变量。添加 unset $(git rev-parse --local-env-vars) 在另一个 repo 上调用 git 命令之前修复了这些问题。我更新了要点脚本,所以它现在应该可以工作了。剩下要做的一件事是检查取消设置所有这些变量是否不会破坏其他东西(例如,如果有更多子模块等)

@编辑 在另一个 repo 上调用 git 命令之前添加的以下两行修复了此行为。测试了 2 个子模块和一次推送的许多提交

unset GIT_ALTERNATE_OBJECT_DIRECTORIES
unset GIT_OBJECT_DIRECTORY