比方在公司不同开发团队中,有一个根底共享库,同时被多个我的项目调用。若要保障根底共享库的动静更新,那么就须要把共享库独立为一个代码库,然而别离把共享库中的文件拷贝到各自的我的项目中会造成冗余,而且再次更新共享库就会在不同我的项目下更新,会比拟麻烦。
利用子模块能够作为解决该类问题的一种计划,子模块容许将一个 Git 仓库作为另一个 Git 仓库的子目录,并且能够独立地治理这个子仓库的版本,而且还能放弃提交的独立性。
上面就通过实操来具体谈谈 Git submodule
一、什么是 Git Submodule
Git Submodule
是 Git 版本控制系统中的一种机制,用于在一个 Git 仓库中蕴含另一个 Git 仓库。它容许将一个 Git 仓库作为另一个 Git 仓库的子目录,并且能够独立地治理这个子仓库的版本,同时还放弃提交的独立。
Submodule 的作用在于,它容许你在一个我的项目中应用其余我的项目的特定版本,而无需将整个子项目的代码复制到主我的项目中。这对于依赖治理和代码复用十分有用。
二、应用 Git Submodule
1 创立和初始化仓库
- 初始化主库和子模块库
我采纳的是 Gitee 来进行本次实操,首先在 Gitee 中创立一个主库 GitSubmoduleDemo
,两个子模块库 ModuleA
和 ModuleB
:
先将主库 clone 到本地:
$ git clone https://gitee.com/haohuin/git-submodule-demo.git
- 在主库中,应用
git submodule add
命令增加Submodule
子模块。
其命令为:git submodule add <remote repo url> <local repo url>
- remote repo url 指近程仓库的 url
- local repo url 指本地仓库的门路 url
// 在主库中增加 ModuleA
$ git submodule add ../module-a.git ModuleA
// 在主库中增加 ModuleB
$ git submodule add ../module-b.git ModuleB
查看以后主库的状态:
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitmodules
new file: ModuleA
new file: ModuleB
发现有新的文件在主库中,别离是 .gitmodules
文件,ModuleA
和 ModuleB
目录
1.1 .gitmodules
文件
首先看一下 .gitmodules
配置文件,它保留了近程仓库 url 与本地仓库 url 门路的映射:
[submodule "ModuleA"]
path = ModuleA
url = ../module-a.git
[submodule "ModuleB"]
path = ModuleB
url = ../module-b.git
每条记录对应一个子模块信息,path 和 url 对应近程仓库 url 和本地仓库门路
1.2 主库中的子模块
接着提交以后主库中呈现的文件和目录:
// 暂存
$ git add .
// 提交
$ git commit -m "ModuleA and ModuleB submodule commit"
[master 2dcfefd] ModuleA and ModuleB submodule commit
3 files changed, 8 insertions(+)
create mode 100644 .gitmodules
create mode 160000 ModuleA
create mode 160000 ModuleB
发现 ModuleA
和 ModuleB
目录的模式编码为 160000
。
在之前解说 index
文件提到过,模式 160000
是援用其余 Git 仓库的非凡文件类型,它容许将一个 Git 仓库作为另一个仓库的子目录进行治理。具体能够看这篇文章 Git 暂存区机制详解
所以此时主库中只是存储了子模块的援用,也就是一次的提交记录。而不是其余的文件或者目录。最初将主库中的批改进行推送:
$ git push origin master
发现在主库中 ModuleA
和 ModuleB
的确是以援用的模式存储的。
2 更新和同步子模块
那么如何将子模块的批改更新到主仓库中呢?这又分两种状况:
- 在子模块所在的仓库中批改代码后提交,而后在主仓库中拉取更新
- 在主仓库中批改子模块代码后提交近程仓库,而后在子模块仓库中拉取更新
2.1 主仓库更新子模块仓库中的批改
首先在子模块仓库 ModuleA 中新增一个文件,并提交到 ModuleA 的近程仓库中:
$ echo "updateModuleA-1">updateModuleA-1.txt
$ git add .
$ git commit -m "update ModuleA"
$ git push
此时子模块仓库中的 commit ID 值为 6026b48
,再来看一下主仓库中的子模块的 Commit ID 值
发现此时主仓库的 Commit ID 值为 3474554
,和子模块仓库中的 ID 值并不同步,所以须要在主仓库的子模块代码中同步子模块近程仓库的更新:
$ cd ModuleA
$ git checkout master
$ git pull origin master
而后在主仓库根目录中提交子模块仓库推送和更新:
$ cd ..
$ git add .
$ git commit -m "update ModuleA"
$ git push
此时发现近程主仓库曾经同步子模块的更新内容,而且 Commit ID 值也同步成6026b48
,和子模块仓库中最新的 Commit ID 保持一致:
2.2 子模块仓库更新主仓库中子模块代码的批改提交
首先在主仓库的子模块目录下批改代码:
// 在主仓库中进入子模块 ModuleA 目录
$ cd ModuleA
// 批改文件和提交和一般 Git 仓库提交流程统一://1. 创立文件并提交
$ echo "ModuleA">updateModuleA.txt
$ git add .
$ git commit -m "update ModuleA"
//2. 推送到近程 ModuleA 仓库
$ git push
发现近程子模块仓库也同步实现:
接着须要将主仓库中的子模块 ModuleA 的变动同步到近程主仓库中具体的操作和上一节主仓库更新子模块仓库中的批改相似,用 add 和 commit 形式提交主仓库的更新,这个时候就实现了子模块和主仓库代码统一。
$ cd ..
$ git add .
$ git commit -m "update ModuleA"
$ git push
在理论的 IDE 环境中,只须要在子模块目录下进行代码批改:
而后在提交时先更新子模块 ModuleB 的近程仓库:
而后再同步近程主仓库中的 ModuleB 目录变动,这一步须要用命令行,间接在主目录提交没法更新近程主目录,然而本地主仓库的 ModuleB 目录的确产生了变动:
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: ModuleB (new commits)
no changes added to commit (use "git add" and/or "git commit -a")
须要命令行切换到主仓库目录执行 git add
后再用 IDE 集成的 Git 提交操作:
$ git add .
再点击提交发现 IDE 中呈现了 ModuleB 的更新变动:
接着推送到近程主仓库即可实现主仓库和子模块仓库的更新
三、总结
本文通过实际介绍子模块:
- 包含子模块的初始化,如何应用 git submodule add 命令在主仓库增加子模块
- 如何在子模块和主仓库之间的更新和同步
子模块次要有以下利用场景
- 不同我的项目间须要共享同一个公共代码, 如根底类库或工具包;
- 较大的我的项目须要拆分成多个子项目进行开发, 通过子模块管制依赖关系;
- 第三方开源库或组件的本地开发与我的项目进行绑定;
- 须要隔离成组和组件版本的同时利用依赖关系, 如微服务架构下的服务与组件;
- 子项目有较强的独立性同时也存在肯定的耦合关系, 通过子模块进行治理。
同时从下面的工夫能够看到,子模块和主仓库之间的同步比较复杂,保护老本高,子模块与主我的项目须要进行严密的协调治理,否则很容易导致不同步的状况呈现。在应用中要结合实际状况下操作,简略的我的项目就不要用子模块,采纳分支治理可能更适合。
参考资料
公共模块治理之 Git Submodule 应用总结
Git – 子模块
《Git 权威指南 蒋鑫著》