devStandard/docs/learning/e-git/2-submodules.md
2025-03-29 14:35:49 +08:00

166 lines
4.0 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Submodule 子模块
https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97#_git_submodules
## 新增
* 添加子模块
```bash
git submodule add <子模块地址> [指定路径(可选)]
# 此时 .gitmodules .git/config .git/modules 会添加子模块的信息
# 子模块目录也会下载,不为空
# 1. 未初始化: 指定分支
git submodule add -b main [URL to Git repo]
# 2. 已初始化: 修改分支
git config -f .gitmodules submodule.DbConnector.branch main
# 这里的 DbConnector 是子模块的名称stable 是分支的名称
# 或者修改.gitmodules
[submodule "path/to/submodule"]
path = path/to/submodule
url = https://github.com/example/repo.git
branch = main
# 更新
git add path/to/submodule
git commit -m "Update submodule to use specific branch"
git submodule update --recursive --remote
```
* 查看
```bash
git status
# 发现只列出 submodule 目录而不是里面所有的文件
# 对于模块外的项目来说,把子模块整个文件夹当成一个文件
```
* 提交
```bash
git add .
git commmit -m 'git add submodule'
```
## 克隆
如果是克隆已经添加了子模块的项目
```bash
# 拉完主项目,此时子模块的目录是空的
git submodule init # 初始化本地配置文件
git submodule update # 拉取对应的提交
# 或者
git submodule update --init --recursive
# 或者在拉取的时候添加参数
git clone <地址> --recurse-submodules
# 子模块不一定是最新的,版本是在主项目里记录的版本
```
## 更新
* 情况1: 子模块的上游更新了, 本地还是旧的
```bash
# 子模块是一个独立的git项目它并不需要知道自己被谁用
cd <子模块目录>
git pull
# 和第一次添加一样, 并不会在status里显示模块里面的文件更新
# submodule的版本控制在于submodule git 的 commit id, 所以要提交这些更新记录
cd <仓库目录>
git add .
git commit -m 'submodule update'
# 或者
git submodule update --remote --recursive # 递归更新子模块
git add .
git commit -m 'submodule update'
```
当项目的子模块很多的时候,可以一个命令更新所有的模块
```bash
git submodule foreach 'git pull origin master'
```
* 情况2: 远程仓库**主项目**的子模块信息更新了, 本地的子模块还是旧的
```bash
# 先更新主项目
git pull origin master
# 再根据主项目里的记录更新本地子模块
git submodule init
git submodule update
```
* 情况3: 对本地的子模块作了个人的修改
不能提交到子模块的仓库, 要自己fork一份再修改
* 情况4: 使用远程仓库覆盖本地的子模块
```sh
cd 子模块的目录
git reset --hard origin/main
```
## 修改模块
如果有子模块的修改权,那么把子模块当成单独的项目修改提交
## 删除模块
```bash
# 不要去手动修改 .gitmodules .git/config .git/modules cached
# 先卸载
git submodule deinit <子模块目录>
# 添加 --force 参数,则子模块内有本地修改,也会被移除
git submodule deinit --force static/platform
# 删除文件夹
git rm <子模块目录>
git commit -m "delete submodule"
```
## 拆分已有文件为子模块
```bash
# 建立新分支
git checkout -b test
# 建立单独的仓库
cd <sub-module>
git init
git add .
git commit -m "version 1.0 of sub-module"
git remote add origin <sub-module-originUrl>
git push -u origin master
# 把文件夹从暂存区和工作区删除
cd ../
git rm -r <sub-module>
git commit -m "remove sub-module directory"
rm -rf <sub-module>
# 注册为子模块
git submodule add <sub-module-originUrl> <sub文件夹>
git commit -m "add submodule version 1.0"
```
* 存在问题点:如果要回到拆分前没有子模块的分支,结果发现提示报错
```bash
error: The following untracked working tree files would be overwritten by checkout:
sub/a.txt
Please move or remove them before you switch branches.
# 可以强制切换, 注意强制切换前保存修改
git checkout -f master
# 再回到test分支发现子模块文件夹空了
cd <sub-module>
# 找回
git checkout .
```