Git Submodule 技术管理规范
1. Git Submodule
Git Submodule 允许将一个独立的 Git 仓库作为另一个仓库的子目录。主仓库(Parent Repository)并不直接存储子仓库的代码,而是记录子仓库的一个特定提交哈希值(Commit SHA-1)作为指针。
- 模式记录:在主仓库中,子模块目录的权限模式记录为
160000,表示这是一个 Git 子模块记录。 - 状态隔离:主仓库与子模块仓库拥有独立的
.git目录和版本历史。
2. 基础配置与初始化
2.1 添加子模块
使用相对路径添加子模块,以确保在 GitLab 实例迁移或不同访问协议(SSH/HTTPS)切换时保持链接有效。
这里的相对路径:
如果我的主项目仓库在 csthenry/yuelaiengine 那么我在主项目仓库添加 Submodule 的时候就可以将 csthenry/ 作为上级目录,即子项目在 csthenry/yuelaiengine-group-plugin,那就可以写为 ../yuelaiengine-group-plugin。
bash
# 格式:git submodule add <相对路径URL> <存放路径>
git submodule add ../yuelaiengine-group-plugin.git plugin/engine_group
git submodule add ../yuelaiengine-group-web-plugin.git web/src/plugin/group
2.2 初始化与克隆
对于初次克隆主仓库的用户,需要通过以下命令同步子模块。
bash
# 克隆主项目时递归下载子模块
git clone --recursive <主项目地址>
# 如果已经克隆了主项目,手动初始化并更新
git submodule update --init --recursive
3. 开发工作流
3.1 子模块代码变更
对子模块内部的代码修改必须遵循“先内部,后外部”的提交顺序。
- 进入子模块目录并检出分支:
bash
cd plugin/engine_group git checkout main - 提交并推送子模块改动:
bash
git add . git commit -m "feat: 实现新功能接口" git push origin main
3.2 主仓库版本对齐
子模块推送完成后,主仓库需要更新其记录的提交指针。
bash
# 回到主仓库根目录
cd ../../
# 将子模块指针的变动加入暂存区
git add plugin/engine_group
# 提交版本对齐记录
git commit -m "chore: 更新插件版本指引至最新提交"
git push origin dev
4. 分支管理与自动化更新
4.1 指定子模块跟踪分支
通过 .gitmodules 配置文件指定子模块默认跟踪的分支(如 main),便于批量同步。
bash
# 设置子模块跟踪分支
git config -f .gitmodules submodule.plugin/engine_group.branch main
# 同步配置到 Git 索引
git submodule sync
4.2 批量同步远程更新
当多个插件仓库均有更新时,可一键同步所有子模块到指定的远程分支版本。
bash
# 根据 .gitmodules 配置拉取所有子模块的远程更新并合并
git submodule update --remote --merge
5. 异常处理与状态维护
5.1 Detached HEAD
执行 git submodule update 后,子模块通常处于游离状态。若需在其中开发,必须先签出分支。
bash
# 检查子模块当前状态
cd <子模块路径>
git branch
# 若为 (HEAD detached at ...),需签出到目标分支
git checkout main
5.2 脏状态修复
若主仓库提示子模块有未提交的改动,通常由未跟踪文件或未提交的本地修改引起。
bash
# 1. 彻底清理子模块内的未跟踪文件
cd <子模块路径>
git clean -fd
# 2. 若仅需重置代码到记录的版本指针
git checkout .
5.3 同步相对路径变更
若手动修改了 .gitmodules 中的 URL,必须执行同步命令。
bash
git submodule sync
6. Go 项目集成建议
由于 yuelai-engine 采用 Go 语言开发,子模块的物理嵌套结构适合结合 Go Workspaces 提升开发体验。
6.1 配置 go.work
在主仓库根目录下创建 go.work 文件,避免在各模块的 go.mod 中使用相对路径 replace。
go
go 1.22
use (
.
./plugin/engine_group
)
7. 移除子模块
删除子模块需要清理配置文件及 Git 缓存。
bash
# 从暂存区移除子模块并删除相应文件
git rm -r <子模块路径>
# 手动删除 .git/modules 下的缓存数据
rm -rf .git/modules/<子模块路径>
# 提交移除操作
git commit -m "refactor: 移除不再使用的子模块"
