Git post-receive钩子远程执行异常:子模块拉取失败
问题:Git checkout --recurse-submodules无法拉取Hugo主题子模块导致构建失败
场景描述
在服务器上配置Git自动化编译Hugo网站并部署到/var/www/html,流程为:创建临时Hugo站点 → 检出目标仓库及其Hugo主题子模块 → Hugo构建静态文件并部署到Web目录。但执行git --work-tree=$TARGET_DIR --git-dir=./ checkout -f --recurse-submodules时,子模块无法正常拉取,导致Hugo因缺少主题无法完成构建。
仓库结构:site.ext仓库包含content/、hugo.toml、static/目录,Hugo主题以Git子模块形式存在。
原脚本
#!/bin/bash # Directory where to work on our site TARGET_DIR=/tmp/site-compile # Public dir where to push the site once compiled PUBLIC_WWW="/var/www/html" BACKUP_WWW=$HOME/site-backup SITE_DOMAIN=https://site.ext # repository logical name REPO="site.ext" # Branch that is going to be deployed to server BRANCH="master" # date to be appended to latest tag NOW=$(date +"%d%m%Y-%H%M") set -xe # delete the working directory first rm -rf $TARGET_DIR # create new temporary site /usr/local/bin/hugo new site $TARGET_DIR # backup public www directory first then setup trap rsync -avz --no-t $PUBLIC_WWW/ $BACKUP_WWW trap "echo 'A problem occurred. Reverting to backup.'; rsync -avz --no-t --del $BACKUP_WWW/ $PUBLIC_WWW; rm -rf $TARGET_DIR" EXIT while read oldrev newrev ref do # if TARGET_DIR is empty we don't want deploy for this project if [[ ! $TARGET_DIR == "" ]]; then if [[ "$GL_REPO" == "$REPO" ]]; then # let's check that we are deploying to the correct branch if [[ $ref = refs/heads/${BRANCH} ]]; then echo "Ref $ref received. Deploying '${BRANCH}' branch to production..." git --work-tree=$TARGET_DIR --git-dir=./ checkout -f --recurse-submodules rm ${TARGET_DIR}/config.toml rm -rf $PUBLIC_WWW/* /usr/local/bin/hugo -s $TARGET_DIR -d $PUBLIC_WWW -b "${SITE_DOMAIN}" -t "dagreynix" --noTimes --minify git tag release_$NOW $BRANCH echo " /===============================" echo " | DEPLOYMENT COMPLETED - ${REPO}" echo " | Target branch: ${BRANCH}" echo " | Target folder: ${PUBLIC_WWW}" echo " | Tag name : release_${NOW}" echo " \===============================" else echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server." fi fi else echo "Target directory not declared. Skipping deploy to server." fi done rm -rf $TARGET_DIR trap - EXIT
问题原因
当使用--work-tree和--git-dir分离Git工作树与仓库目录时,checkout --recurse-submodules参数无法正确触发子模块的初始化与更新。Git在这种分离模式下,不会自动关联子模块的目录结构,导致子模块内容无法拉取到指定的工作树路径。
解决方法
将原脚本中的checkout命令拆分为两步:先执行分支检出,再单独初始化并更新子模块,明确指定工作树路径:
替换原脚本中:
git --work-tree=$TARGET_DIR --git-dir=./ checkout -f --recurse-submodules
为:
# 先检出主仓库分支到目标工作树 git --work-tree=$TARGET_DIR --git-dir=./ checkout -f # 初始化并递归更新所有子模块到目标工作树 git --work-tree=$TARGET_DIR --git-dir=./ submodule update --init --recursive
修正后完整脚本
#!/bin/bash # Directory where to work on our site TARGET_DIR=/tmp/site-compile # Public dir where to push the site once compiled PUBLIC_WWW="/var/www/html" BACKUP_WWW=$HOME/site-backup SITE_DOMAIN=https://site.ext # repository logical name REPO="site.ext" # Branch that is going to be deployed to server BRANCH="master" # date to be appended to latest tag NOW=$(date +"%d%m%Y-%H%M") set -xe # delete the working directory first rm -rf $TARGET_DIR # create new temporary site /usr/local/bin/hugo new site $TARGET_DIR # backup public www directory first then setup trap rsync -avz --no-t $PUBLIC_WWW/ $BACKUP_WWW trap "echo 'A problem occurred. Reverting to backup.'; rsync -avz --no-t --del $BACKUP_WWW/ $PUBLIC_WWW; rm -rf $TARGET_DIR" EXIT while read oldrev newrev ref do # if TARGET_DIR is empty we don't want deploy for this project if [[ ! $TARGET_DIR == "" ]]; then if [[ "$GL_REPO" == "$REPO" ]]; then # let's check that we are deploying to the correct branch if [[ $ref = refs/heads/${BRANCH} ]]; then echo "Ref $ref received. Deploying '${BRANCH}' branch to production..." git --work-tree=$TARGET_DIR --git-dir=./ checkout -f git --work-tree=$TARGET_DIR --git-dir=./ submodule update --init --recursive rm ${TARGET_DIR}/config.toml rm -rf $PUBLIC_WWW/* /usr/local/bin/hugo -s $TARGET_DIR -d $PUBLIC_WWW -b "${SITE_DOMAIN}" -t "dagreynix" --noTimes --minify git tag release_$NOW $BRANCH echo " /===============================" echo " | DEPLOYMENT COMPLETED - ${REPO}" echo " | Target branch: ${BRANCH}" echo " | Target folder: ${PUBLIC_WWW}" echo " | Tag name : release_${NOW}" echo " \===============================" else echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server." fi fi else echo "Target directory not declared. Skipping deploy to server." fi done rm -rf $TARGET_DIR trap - EXIT
内容的提问来源于stack exchange,提问作者danix
相关产品推荐
相关产品推荐

