为什么
为什么要将代码仓作为子模块?有什么优势?
- 精确版本控制:父仓记录子仓的commit哈希值,确保代码版本固定,避免隐式升级导致的兼容性问题
- 模块化管理:将独立仓库作为子模块嵌入父仓,实现代码物理隔离,支持多团队写作与独立开发
- 代码复用与共享:同一模块可被多个项目引用,避免重复代码,确保一致性
- 权限与协作分离:子模块独立管理,父仓开发者无需介入子模块开发流程
父子仓项目结构
python
主仓库:Project/
├── 子模块A (通过submodule链接仓库)
├── 子模块B
└── 子模块C
相关操作
1. 添加子仓
bash
git submodule add <repo> <Current_DIR Path>
添加以后,git会在父仓create两个文件:
-
new file------> .gitmodules (保存子仓作为子模块所在的路径以及repo_url)
-
new file -------> repo_file(子仓,由于是通过哈希值链接,所以是以file的形式存储而不是dir)
2. 更新子仓commit
在开发过程中,子仓会不断commit,所以父仓要随时或者定期的进行update submodule。
update 子仓commit:
bash
git submodule update --remote <Current_DIR Path>
执行完上面操作后,本地submodule更新了,但是父仓remote尚未更新,所以需要单独push一下repo_file(保证父仓commit哈希与子仓最新commit一致):
bash
git add <Current_DIR Path>
git commit -m "update submodule"
git push origin cc/appworld
3. 相同路径更换子仓
有时候我们可能需要在相同路径下更换不同的仓库作为submodule,该操作需要
删除:
- 该路径下submodule的git索引
- 彻底删除子模块的内部 Git 配置目录
- 删除物理文件
code options:
bash
# 查看该submodule是否被git追踪
git ls-files | grep <submodule_path>
# 删除git索引
git rm --cache <submodule_path>
# 彻底删除子模块的配置信息 确保路径干净
rm -rf .git/modules/<submodule_path>
# 将新仓库作为子仓链接 (忽略冲突)
git submodule add -f <new_repo_url> <submodule_path>
补充:
-->git的索引是暂存区,记录了哪些文件需要被提交到仓库,--cache选项表示从索引中移除该文件不再追踪,但是物理文件还是在的,所以需要手动删除一下物理文件然后重新submodule add
--> git子模块本质是一个嵌套的git仓库,其配置和对象都存储在.git/modules/<submodule_path>,rm -rf会强制递归删除路径下所有内容。相当于彻底清除子模块与git的联系。
--> git submodule add -f 中 -f是强制重新添加,避免忘记删除物理文件导致的existing error(忽略冲突)
还有一个更为便捷的方法,直接更新子模块的url:
bash
git submodule set-url <path> <new-url>
该操作仅仅更新仓库url并不会将原有仓库的文件进行更替或者删除
4. 子模块中包含其他子模块
如果你需要添加的子仓中也潜逃了子仓,那么需要执行下面命令进行添加
bash
# 初始化并更新嵌套子模块
git submodule update --init --recursive
# 克隆主仓库时自动初始化嵌套子模块
git clone --recurse-submodules --recursive <main-repo-url>