暗黑模式
子模块
教程Git
介绍
submodule: 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
参考:
示例
初始化主仓库A并添加子模块B
bash
# init A if needed
mkdir A
cd A
git init
# add submodule B to A, assume that B is ui-vuetify
git submodule add [-b branch] https://gitee.com/jinyuan-ming/ui-vuetify.git libs/ui-vuetify
git submodule status # check if submodule is added
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
此时,主仓库目录中多出以下文件:
.gitmodules
.git/modules/
bash
# 提交主仓库代码
git add .gitmodules libs/ui-vuetify
git commit -m "Add submodule: ui-vuetify"
1
2
3
2
3
拉取子模块最新代码
bash
# 拉取主仓库记录的子模块版本
git submodule update [path/to/submodule]
# 或拉取子模块远程仓库最新代码并自动合并
git submodule update --remote --merge [path/to/submodule]
# 提交主仓库变动(如果有的话)
git add libs/ui-vuetify
git commit -m "update submodule to latest version"
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
使用子模块的特定标签
bash
cd path/to/submodule
git tag # list all tags of submodule
git checkout v1.0.0
# 提交主仓库变动
cd ..
git add path/to/submodule
git commit -m "Update submodule to tag v1.0.0"
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
修改子模块代码并提交
bash
cd path/to/submodule
touch README.md
git add README.md
git commit -m 'add README.md'
git push
1
2
3
4
5
2
3
4
5
删除子模块
bash
git submodule deinit -f path/to/submodule
git rm -f path/to/submodule
1
2
2
协同开发
当别人克隆主仓库时,需要初始化子模块:
bash
# 方法一:
git clone <A_repo_url>
cd A
git submodule update --init --recursive [path_to_submodule]
# 方法二:
git clone --recurse-submodules <A_repo_url> # 等同于 clone 之后立马执行 `git submodule update --init --recursive`
1
2
3
4
5
6
7
2
3
4
5
6
7
git submodule
命令说明
git submodule init
和 git submodule update
是两个不同的命令,用于管理 Git 子模块,主要区别如下:
git submodule init
- 作用:
init
命令会根据主仓库中的.gitmodules
文件,将子模块的配置信息写入到本地的.git/config
文件中。 - 功能:
git submodule init
仅仅是初始化子模块配置,不会下载子模块内容,也不会更新子模块的文件。 - 场景:通常在第一次克隆主仓库并且希望设置子模块时使用。
- 示例:bash
git submodule init
1
git submodule update
- 作用:
update
命令会从远程仓库拉取子模块的内容,并将子模块的代码检出到指定的提交(主仓库中记录的子模块提交哈希)。 - 功能:
git submodule update
会下载子模块的内容,使子模块目录中包含实际的代码文件。 - 场景:当你需要拉取子模块的代码到本地或更新子模块的内容时使用。
- 常用参数:
--init
:如果子模块还未初始化,update
时加上--init
可以同时完成初始化和更新操作。--recursive
:递归更新子模块中的子模块。
- 示例:bash
git submodule update --init --recursive
1
总结
git submodule init
:仅初始化子模块的配置信息,不会拉取代码。git submodule update
:拉取子模块的代码并检出到指定的提交。
一般在克隆主仓库后,可以使用以下命令来同时完成初始化和更新子模块的代码:
bash
git submodule update --init --recursive
1
这样可以确保所有子模块都正确初始化并下载到本地。
Notices
切换分支导致主仓库识别子模块改动
- 当前处于
master
分支,子模块是7777777
git submodule update --init
检出子模块7777777
- 切换到
develop
分支,子模块是99999999
,但是本地子模块仍然是7777777
git status
显示子模块有new commits
- 此时不能
git add,commit,push
,正确做法是:git submodule update
,把子模块更新到develop
分支对应的子模块版本
Troubleshooting
本地仓库的子模块 COMMIT HASH 和远程仓库不一致
可能原因:分支不同导致的,例如本地处于 develop
分支,但对比的远程仓库分支却是 master
。