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

4.0 KiB
Executable File
Raw Blame History

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

新增

  • 添加子模块
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
  • 查看
git status
# 发现只列出 submodule 目录而不是里面所有的文件
# 对于模块外的项目来说,把子模块整个文件夹当成一个文件
  • 提交
git add .
git commmit -m 'git add submodule'

克隆

如果是克隆已经添加了子模块的项目

# 拉完主项目,此时子模块的目录是空的
git submodule init # 初始化本地配置文件
git submodule update # 拉取对应的提交
# 或者
git submodule update --init --recursive

# 或者在拉取的时候添加参数
git clone <地址> --recurse-submodules
	
# 子模块不一定是最新的,版本是在主项目里记录的版本

更新

  • 情况1: 子模块的上游更新了, 本地还是旧的
# 子模块是一个独立的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'

当项目的子模块很多的时候,可以一个命令更新所有的模块

git submodule foreach 'git pull origin master'
  • 情况2: 远程仓库主项目的子模块信息更新了, 本地的子模块还是旧的
# 先更新主项目
git pull origin master
# 再根据主项目里的记录更新本地子模块
git submodule init
git submodule update
  • 情况3: 对本地的子模块作了个人的修改

    不能提交到子模块的仓库, 要自己fork一份再修改

  • 情况4: 使用远程仓库覆盖本地的子模块

cd 子模块的目录
git reset --hard origin/main

修改模块

如果有子模块的修改权,那么把子模块当成单独的项目修改提交

删除模块

# 不要去手动修改 .gitmodules .git/config .git/modules cached
# 先卸载
git submodule deinit <子模块目录>
# 添加 --force 参数,则子模块内有本地修改,也会被移除
git submodule deinit --force static/platform
# 删除文件夹
git rm <子模块目录>
git commit -m "delete submodule"

拆分已有文件为子模块

# 建立新分支
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"
  • 存在问题点:如果要回到拆分前没有子模块的分支,结果发现提示报错
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 .