Git Submodule 是 Git 中用于管理嵌套仓库依赖的功能,允许你将一个 Git 仓库作为另一个仓库的子目录,同时保持独立的提交历史和版本控制。它非常适合管理第三方依赖或共享模块。
核心概念
- 独立仓库:子模块是一个完整的 Git 仓库,独立于主仓库。
- 固定提交记录:主仓库记录子模块的特定提交(而非分支),确保依赖稳定性。
- 跟踪状态:主仓库跟踪子模块的当前状态(提交哈希)。
使用场景
- 主项目依赖另一个项目的特定版本(如第三方库)。
- 多项目共享公共组件(如工具库、UI 组件)。
操作示例
1. 添加子模块
# 主仓库中操作:添加子模块
git submodule add https://github.com/user/submodule-repo.git libs/submodule-repo
- 这会:
- 克隆
submodule-repo
到libs/submodule-repo
目录。 - 生成
.gitmodules
文件,记录子模块信息。 - 将子模块的当前提交哈希保存到主仓库。
- 克隆
提交改动到主仓库:
git commit -m "Add submodule submodule-repo"
2. 克隆含子模块的项目
克隆主仓库后,子模块目录是空的!需额外操作:
git clone https://github.com/user/main-project.git
cd main-project
# 初始化子模块配置
git submodule init
# 拉取子模块内容(检出主仓库记录的提交)
git submodule update
# 或者一步完成:
git submodule update --init --recursive
3. 更新子模块
当子模块仓库有更新时:
方法 1:更新到主仓库记录的提交
# 进入子模块目录
cd libs/submodule-repo
# 拉取子模块的更新
git fetch
git checkout main # 切换到需要的分支
git pull
# 返回主仓库目录
cd ../../
# 提交子模块的新状态
git add libs/submodule-repo
git commit -m "Update submodule to latest commit"
方法 2:强制更新到子模块远程最新
# 主仓库中直接更新子模块到远程最新提交(默认跟踪分支)
git submodule update --remote
git commit -am "Update submodule to remote latest"
4. 删除子模块
# 1. 删除子模块配置
git submodule deinit libs/submodule-repo
# 2. 移除 Git 跟踪
git rm libs/submodule-repo
# 3. 提交更改
git commit -m "Remove submodule"
注意事项
- 修改子模块:需在子模块目录内提交并推送(和普通 Git 仓库操作一致)。
-
递归子模块:若子模块还包含子模块,使用
--recursive
参数初始化:git submodule update --init --recursive
- 固定版本:主仓库记录的始终是子模块的某个提交哈希,而非分支名。
典型问题
-
空子模块目录:克隆主仓库后未运行
git submodule update
。 - 子模块更新冲突:主仓库和子模块的修改需分别提交。
替代方案对比
方案 | 适用场景 |
---|---|
Git Submodule | 需要精确控制依赖版本 |
Git Subtree | 将子项目合并到主仓库(历史混合) |
包管理工具 | 非代码依赖(如 npm、pip) |
子模块适合需要代码级依赖且需保持独立历史的场景。