编写Shell脚本:将Git仓库及递归子模块克隆为工作区独立目录
问题
我有一个Git仓库(abc),它包含两个子模块,且这两个子模块共同包含一个子模块。我需要编写一个Shell脚本,仅输入该仓库(abc)的URL,就能将其克隆到workspace目录中。我已通过git clone <url> --recursive命令完成基础克隆,但还希望脚本能将所有子模块仓库也递归克隆到workspace目录中(而非作为克隆后abc仓库的子目录)。最终workspace目录应包含4个子目录:abc、submod1、submod2、common_submod。请问这可以通过Shell脚本实现吗?
解答
当然可以实现,以下是一个满足需求的Shell脚本:
#!/bin/bash # 检查输入参数是否合法 if [ $# -ne 1 ]; then echo "用法: $0 <abc仓库的URL>" exit 1 fi ABC_REPO_URL="$1" WORKSPACE_DIR="./workspace" # 创建workspace目录并进入 mkdir -p "$WORKSPACE_DIR" cd "$WORKSPACE_DIR" || { echo "无法进入workspace目录"; exit 1; } # 克隆主仓库abc到workspace/abc echo "开始克隆主仓库abc..." git clone "$ABC_REPO_URL" abc cd abc || { echo "无法进入abc目录"; exit 1; } # 提取主仓库中所有直接子模块的URL和名称 # 获取子模块URL列表 SUBMODULE_URLS=($(git config --file .gitmodules --get-regexp 'submodule\..*\.url' | awk '{print $2}')) # 获取子模块路径并提取目录名 SUBMODULE_NAMES=($(git config --file .gitmodules --get-regexp 'submodule\..*\.path' | awk '{print $2}' | xargs -I {} basename {})) # 返回workspace根目录 cd .. || exit 1 # 克隆每个直接子模块到workspace根目录,并处理公共子模块 echo "开始克隆直接子模块..." for index in "${!SUBMODULE_URLS[@]}"; do REPO_URL="${SUBMODULE_URLS[$index]}" MODULE_NAME="${SUBMODULE_NAMES[$index]}" # 如果子模块目录不存在则克隆 if [ ! -d "$MODULE_NAME" ]; then git clone "$REPO_URL" "$MODULE_NAME" # 进入子模块目录,提取公共子模块信息 cd "$MODULE_NAME" || continue COMMON_SUBMOD_URL=$(git config --file .gitmodules --get-regexp 'submodule\..*\.url' | awk '{print $2}') COMMON_SUBMOD_NAME=$(git config --file .gitmodules --get-regexp 'submodule\..*\.path' | awk '{print $2}' | xargs basename) cd .. || continue # 如果公共子模块未克隆,则克隆到workspace根目录 if [ ! -d "$COMMON_SUBMOD_NAME" ]; then echo "开始克隆公共子模块$COMMON_SUBMOD_NAME..." git clone "$COMMON_SUBMOD_URL" "$COMMON_SUBMOD_NAME" fi fi done echo "所有仓库克隆完成,当前workspace目录结构:" ls -l
脚本说明
- 参数校验:确保用户传入正确数量的参数,否则提示用法。
- 目录准备:自动创建
workspace目录并进入,避免手动操作。 - 主仓库克隆:将
abc仓库克隆到workspace/abc,保留原仓库结构。 - 子模块提取:通过读取
.gitmodules文件,获取主仓库的直接子模块的URL和名称。 - 子模块克隆:将每个直接子模块克隆到
workspace根目录,同时检查并克隆公共子模块(仅克隆一次,避免重复)。 - 结果验证:最后打印
workspace的目录结构,确认所有目标目录存在。
注意事项
- 脚本假设每个直接子模块仅包含
common_submod这一个公共子模块,如果有其他子模块,需要调整提取逻辑。 - 若子模块使用相对URL,需确保Git能正确解析(建议使用绝对URL以避免路径问题)。
- 脚本会跳过已存在的目录,适合重复执行场景。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

