我两天前偶然看到了这个主题,当时我也在苦苦挣扎。最终找到了一个简洁明了的解决方案,并在这里写了一篇文章:
Git push with submodules: a how-to guide
我意识到,如果我要向裸仓库(push)发送请求,只是为了使用post-receive来从非裸仓库(pull)中提取信息,那么我不妨简单地直接向非裸仓库推送(push)。 在这种情况下,“最佳实践”只会增加复杂性。
如遇链接失效,请查看以下解决方案,省略我遇到与您相同的所有问题的部分。
首先,让我们创建一个“通用”的post-receive钩子(universal post-receive hook),一个无需按每个存储库更改的钩子。
[aaron@aaronadams]$ cat > /usr/local/share/git-core/templates/hooks/post-receive.sample
while read oldrev newrev refname
do
:
done
unset GIT_DIR
cd `git config --get core.worktree` || exit
git checkout --force
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
Initialized empty Git repository in /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca/.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
天啊,它行了!
这种方法不仅能兼容子模块,还只需要一个命令来设置新的远程仓库(好吧,由四个命令组成)。它还将仓库和工作树放在同一个位置;并且我们的配置或挂钩文件中不需要绝对路径,现在也是完全可移植的。
我希望这个答案能像其他人的 Stack Exchange 帖子一样,在过去的两天里帮助某些人!