【Git】git-submodule子模块管理

Git Submodule 子模块管理

什么是 Submodule?

当一个项目需要包含并引用其他独立的 Git 仓库时,可以使用 Git Submodule(子模块)。

典型场景:

  • 一个 monorepo 主项目包含多个独立子项目,各子项目有各自的远程仓库和提交历史
  • 项目依赖一个外部库,且希望跟踪该库的特定版本
  • 多端项目(如后端 + 前端 + 小程序)各自独立仓库,但需要一个主仓库统一管理

Submodule 的本质 :主仓库并不保存子模块的文件内容,只保存一个指向子模块某个 commit 的引用 (指针)。主仓库的 .gitmodules 文件记录子模块的路径和远程地址。

与直接把子项目代码放进主仓库的区别:子模块保持独立的提交历史和远程仓库,主仓库只追踪"当前使用的是子模块的哪个版本"。

实战:主仓库管理三端子项目

以我的点餐项目 cm-food-ordering 为例,主仓库管理三个子仓库:

复制代码
cm-food-ordering/          ← 主仓库
├── backend/               ← submodule(fork 自 RuoYi-Vue-Plus)
├── frontend/              ← submodule(fork 自 plus-ui)
└── uniapp/                ← submodule(独立项目)

1. 添加子模块

bash 复制代码
# 语法:git submodule add <子仓库远程地址> <本地目录名>
git submodule add https://gitee.com/dream-deeply-tyu/RuoYi-Vue-Plus.git backend
git submodule add https://gitee.com/dream-deeply-tyu/plus-ui.git frontend
git submodule add https://gitee.com/dream-deeply-tyu/cm-food-ordering-uniapp.git uniapp

执行后会:

  • 在对应目录克隆子仓库
  • 生成 .gitmodules 文件(记录子模块配置)
  • 在主仓库暂存 .gitmodules 和各子模块目录

2. 查看 .gitmodules 文件

ini 复制代码
[submodule "backend"]
	path = backend
	url = https://gitee.com/dream-deeply-tyu/RuoYi-Vue-Plus.git
[submodule "frontend"]
	path = frontend
	url = https://gitee.com/dream-deeply-tyu/plus-ui.git
[submodule "uniapp"]
	path = uniapp
	url = https://gitee.com/dream-deeply-tyu/cm-food-ordering-uniapp.git

3. 提交主仓库

bash 复制代码
git add .gitmodules backend frontend uniapp
git commit -m "chore: 改用 submodule 管理三端子仓库"
git push

克隆含子模块的项目

方式一:一步到位(推荐)

bash 复制代码
git clone --recurse-submodules https://gitee.com/dream-deeply-tyu/cm-food-ordering.git

--recurse-submodules 会在克隆主仓库的同时初始化并拉取所有子模块。

方式二:先克隆,再初始化子模块

bash 复制代码
# 先克隆主仓库(子模块目录是空的)
git clone https://gitee.com/dream-deeply-tyu/cm-food-ordering.git
cd cm-food-ordering

# 初始化并拉取所有子模块
git submodule update --init --recursive

如果子模块里面还嵌套了子模块,--recursive 参数会递归处理。

日常开发流程

修改子模块代码并同步到主仓库

bash 复制代码
# 1. 进入子模块目录,正常开发提交
cd backend
git add -A
git commit -m "feat: 新增点餐业务模块"
git push origin cm-food-ordering

# 2. 回到主仓库,更新 submodule 指针
cd ..
git add backend
git commit -m "chore: bump backend submodule"
git push

关键点 :子模块代码改动后,主仓库会显示子模块有新提交(modified: backend (new commits))。需要在主仓库额外提交一次,记录子模块指向的新 commit。

切换子模块分支

子模块默认会处于"detached HEAD"状态(指向某个具体的 commit,不在任何分支上)。要开发需要先切到分支:

bash 复制代码
cd backend
git checkout cm-food-ordering
# 之后正常开发提交

查看子模块状态

bash 复制代码
# 查看所有子模块的当前状态
git submodule status

# 输出示例:
# +a043dbd61c... backend (cm-food-ordering)
#  3964bb7... frontend (cm-food-ordering)
#  cc35188... uniapp (cm-food-ordering)
# 前面的 + 表示子模块有未提交的改动

更新子模块到最新版本

当子模块远程仓库有新提交(比如其他协作者推送了代码),主仓库需要同步:

bash 复制代码
# 方式一:进入子模块目录拉取
cd backend
git pull origin cm-food-ordering
cd ..
git add backend
git commit -m "chore: update backend submodule"

# 方式二:在主仓库统一更新所有子模块
git submodule update --remote
git add backend frontend uniapp
git commit -m "chore: update all submodules"

git submodule update --remote 会拉取每个子模块远程对应分支的最新提交,但不会自动切换子模块的 HEAD,需要再 git add + git commit 记录新指针。

删除子模块

Git 没有提供 git submodule remove 命令,需要手动操作:

bash 复制代码
# 1. 从 .git/config 中移除子模块配置
git submodule deinit -f backend

# 2. 从主仓库索引中移除
git rm -f backend

# 3. 删除 .gitmodules 中的相关条目(如果没有其他子模块,直接删文件)
# 4. 删除 .git/modules/ 下的子模块缓存
rm -rf .git/modules/backend

# 5. 提交
git commit -m "chore: 移除 backend 子模块"

子模块的注意事项

  1. 主仓库只保存指针 :主仓库不存储子模块的文件内容,只记录子模块当前指向的 commit hash。克隆主仓库时必须用 --recurse-submodules 或手动 git submodule update --init。

  2. 子模块默认是 detached HEAD :克隆后子模块不在任何分支上,开发前需要手动 git checkout <branch>。

  3. 子模块改动需双重提交:在子模块内提交后,还要在主仓库提交一次指针更新。容易忘记第二步,导致主仓库记录的子模块版本是旧的。

  4. 不要在主仓库直接修改子模块文件:虽然技术上可行,但容易造成混乱。应该进入子模块目录操作。

  5. 切换主仓库分支时注意子模块状态 :git checkout 主仓库分支后,子模块可能不会自动切换到对应版本,需要 git submodule update。

学习参考

相关推荐
全栈陈序员21 小时前
Git】从入门到精通(八)—— git log:查看提交历史
大数据·git·elasticsearch
7177771 天前
Git自建用什么工具比较好:Gitea、Forgejo、GitLab CE与Gitee的选型对比
git·gitlab·gitea
lsc_blog2 天前
年底还在招的岗位,先确认缺口和到岗要求
git·缓存·ci/cd·职场和发展·github
全栈陈序员2 天前
【Git】从入门到精通(十一)—— git reset 三种模式详解
git·elasticsearch
全栈陈序员2 天前
【Git】从入门到精通(十)—— 撤销与恢复:git checkout与git restore
运维·网络·数据库·git
全栈陈序员2 天前
【Git】从入门到精通(五)—— git add:将文件加入暂存区
大数据·git·elasticsearch
全栈陈序员3 天前
【Git】从入门到精通(七)—— git status:查看仓库状态
大数据·git·elasticsearch
莫晓燚3 天前
Ansible 13 个常用模块---企业实战
git·github
无言听风雨丶3 天前
Kubernetes GitOps 持续交付实战:用 Argo CD 让 Git 成为集群事实源
git·elasticsearch·kubernetes