5

在更新后挂钩中使用以下代码时是否可以包含子模块?

GIT_WORK_TREE=/path/to/directory git checkout -f

我还必须有哪些其他选项来分发代码,包括来自更新后挂钩的子模块?

谢谢。

4

1 回答 1

11

问题“在后挂钩上使用git submodule update --init”提到了如果在挂钩中使用它可以看到的错误消息post-update

GIT_WORK_TREE=/path/to/directory git submodule update --init

那将给出一个:

remote: You need to run this command from the toplevel of the working tree.

所以最好cd直接在目标仓库中运行你的命令:

export GIT_DIR=$(pwd)

cd /path/to/target/workingtree

git checkout -f master
git submodule update --init --recursive

但是,如“在推送到裸工作目录后如何在工作树中初始化/更新 git 子模块? ”中所示:

看起来当您运行“git submodule update”时您无法设置GIT_WORK_TREE
它将尝试将其用作子模块的工作树,而不是超级项目

Aaron Adams的博文“ Git push with submodules: a how-to guide ”描述了与OP iliveinapark评论中显示的类似错误消息:

可悲的是,这不起作用,我怀疑是因为我的回购是一个裸回购。
我遵循这些命令得到的错误是:

fatal: This operation must be run in a work tree

如果,为了克服上述错误,我使用类似的东西:

git --git-dir=<my bare repo> --work-tree=<where I export to> submodule update --init --recursive 

我得到:

fatal: working tree '<where I export to>' already exists. Clone of '<submodule repo>' into submodule path '<submodule path>' failed

上面提到的博客文章建议了一种基于非裸仓库的方法(通常建议推送到,但在这种情况下是必要的):

使用 Git 管理带有子模块的网站:正确的方法

首先,让我们创建一个通用的 post-receive 挂钩,我不需要在每个存储库的基础上进行更改:

[aaron@aaronadams]$ cat > /usr/local/share/git-core/templates/hooks/post-receive.sample
#!/bin/sh
#
# An example hook script to update the working tree, including its
# submodules, after receiving a push.
#
# This hook requires core.worktree to be explicitly set, and
# receive.denyCurrentBranch to be set to false.
#
# To enable this hook, rename this file to "post-receive".

# Read standard input or hook will fail
while read oldrev newrev refname
do
:
done

# Unset GIT_DIR or the universe will implode
unset GIT_DIR

# Change directory to the working tree; exit on failure
cd `git config --get core.worktree` || exit

# Force checkout
git checkout --force

# Force update submodules
git submodule update --init --recursive --force
[aaron@aaronadams]$ chmod +x /usr/local/share/git-core/templates/hooks/post-receive.sample

现在让我们继续打破所有规则。

我们要:

  • 在我们的网站目录中初始化一个非裸 Git 存储库;
  • 确保它可以从 git push 接收;
  • 将其工作树显式设置为其父目录;
  • 并启用我们刚刚创建的钩子。
[aaron@aaronadams]$ cd /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca
[aaron@aaronadams]$ git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../ && mv .git/hooks/post-receive.sample .git/hooks/post-receive
在 /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca/.git/ 中初始化空的 Git 存储库

最后,在我们的本地机器上,我们将更改远程以反映我们新存储库的位置,然后推送。

[aaron@aaronadams]$ git remote set-url staging aaron@aaronadams.ca:sites/staging.aaronadams.ca
[aaron@aaronadams]$ git push staging master
remote: Submodule 'codeigniter' (git://github.com/EllisLab/CodeIgniter.git) registered for path 'codeigniter'
remote: Cloning into 'codeigniter'...
remote: Submodule path 'codeigniter': checked out 'fd24adf31255822d6aa9a5d2dce9010ad2ee4cf0'
To aaron@aaronadams.ca:sites/staging.aaronadams.ca
 * [new branch]      master -> master

天哪,它奏效了!

这种方法不仅与子模块兼容,还只需要一个命令来设置一个新的远程存储库(好吧,它由四个命令组成)。
它还将存储库和工作树保持在同一位置;并且在我们的配置或钩子文件中不需要绝对路径,它现在也完全可移植


OP iliveinapark提到

不过,这变得有点太繁琐了,所以我进行了简单的强制结帐,并将管理手动更新我的子模块。

于 2013-04-15T06:04:50.907 回答