如何将子模块推送到远程存储库

How to push a submodule to a remote repository

我在服务器上设置了一个远程存储库。我从我的本地计算机推送到存储库,并设置了一个挂钩以将推送重定向到另一个目录。它看起来像这样:

post-receive

#!/bin/sh
git --work-tree=/var/www/laravel --git-dir=/var/repo/site.git checkout -f main

当我去 /var/www/laravel 并尝试做

git submodule init
git submodule update

它给出:

fatal: not a git repository (or any of the parent directories): .git

我知道我可能必须在重定向推送之前启动和更新子模块。我可能必须创建另一个挂钩命令,但我不知道它应该是什么。谢谢!

[某些现有裸存储库的 post-receive 脚本包含行]

git --work-tree=/var/www/laravel --git-dir=/var/repo/site.git checkout -f main

[但是]

When I go to /var/www/laravel and try to do

git submodule init
git submodule update

It gives:

fatal: not a git repository (or any of the parent directories): .git

错误本身当然是正确的。问题是 /var/www/laravel 没有 .git:既没有指向存储库位置的 .git 文件,也没有 .git 目录/文件夹(无论您喜欢哪个术语)包含存储库。简而言之,它是一个工作树只是因为 执行 操作 Git 包含 --work-tree=/var/www/laravel.[=46= 的一些其他 git ... 命令]

因此,直接的解决方案是 运行:

git --git-dir=/var/repo/site.git submodule init
git --git-dir=/var/repo/site.git submodule update

或同等学历。但是请注意,子模块涉及克隆额外的 Git 存储库,并且相同的推理 - 无论它是什么 - 导致你 not 将 Git 存储库本身放入/var/www/laravel/.git 首先可能 会导致您避免在 /var/www/laravel 的子目录中放置额外的 .git 条目。这将更难实现。

If—这是一个相当大的 if—可以将 .git 文件留在子模块工作树中,如果(另一个相当大的 if)测试显示如果一切正常,请考虑阅读您的 post-receive 脚本:

# configuration: where the directory and submodules go
wt=/var/www/laravel

export GIT_DIR=$(realpath $GIT_DIR) &&
git --work-tree=$wt checkout -f main &&
cd $wt &&
git submodule update --init

这里的想法是:

  1. 我们采用 $GIT_DIR,它在 post-receive 脚本中设置,但通常是 相对 路径,例如 .git.,并将其转换为绝对路径。 (abspath 函数在这里可能会更好,但它不如 realpath 命令可用。)

  2. 然后我们使用 git --worktree 来检查 main 末尾的提交。如果这可能会覆盖一些未保存的文件,则需要此处的 -f 选项。这种方法非常不完美,一次准备一个完整的工作树会好得多,然后用 nearly-atomic mv 交换它,但我们在这里坚持使用现有的钩子方法。我们所做的只是删除 --git-dir,它隐含在 $GIT_DIR 变量中。

  3. 然后我们在目标工作树中 运行 git submodule update --init$GIT_DIR 仍然设置为绝对路径。这结合了 initupdate 步骤。与结帐步骤一样,它相当不完善。我们可以在第二步中使用 git checkout --recurse-submodules 来达到类似的效果,并且在某些(更新的)Git 版本中可能会更好。

将备选方案(递归结帐)与原子交换相结合,我们得到类似这样的东西作为我们的 post-receive:

wt=/var/www/laravel.update-tmp.$$
rm -rf $wt # just in case
export GIT_INDEX_FILE=$GIT_DIR/index.tmp.$$
rm -f $GIT_INDEX_FILE # also just in case
mkdir $wt
git --work-tree=$wt checkout --recurse-submodules main
rm -f $GIT_INDEX_FILE

t=/var/www/laravel

# We now try to put $wt in place of $t with as little
# interruption as possible.  This means renaming the
# existing $t out of the way (using a pid-based directory
# name), renaming $wt into place, and only then removing
# (recursively) the backup.
mv $t $t.backup.$$ && mv $wt $t && rm -rf $t.backup.$$

如果您愿意,可以将各个单独的行 运行g 组合成一个大的 && 链,或者您可以在顶部使用 set -e。请注意,以上内容完全未经测试。