git之submodule
当一个项目很大很复杂时,可以将项目分为几个模块分别进行管理;或者,当一个项目引用第三方开源代码,可以将这些第三方开源代码单独进行管理,这样做是为了代码隔离,方便项目维护。这时可以使用git的submodule功能,git submodule允许你将一个 git 仓库作为另一个 git 仓库的子目录。
git submodule用于多模块(仓库)管理,其父项目与子项目提交是分开的,父项目提交只包含子项目的信息,而不会包括子项目的代码,子项目使用独立的commit、push、pull操作。
简单来说:父项目git仓库管理父项目内容和子项目信息;子项目git仓库管理子项目内容。
常用命令:
git submodule add # 添加子模块
git submodule init # 初始化子模块
git submodule update # 更新子模块
git clone --recursive # 递归的方式克隆整个项目:
git submodule foreach git pull # 拉取所有子模块
git submodule foreach git checkout master # 所有子模块切到master分支
git submodule update --init --recursive # 作用是确保所有子模块都被正确地初始化和更新到仓库中的最新状态
1 添加、同步子模块
这里通过一个示例来展示git submodule的使用。
1.1 添加一个模块
环境准备:
首先需要准备一个父项目与一个子项目。详细步骤见参考3《如何将本地代码推送至github》
- 在github上新建一个父项目 submodule_main;并在本地新建工程,与github库绑定
mkdir submodule_main
cd submodule_main
echo "## submodule_main" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:sz-ok/submodule_main.git
git push -u origin main
- 同样,在github上新建一个子项目submodule_subdir;并在本地新建工程,与github库绑定
mkdir submodule_subdir
cd submodule_subdir
echo "## submodule_subdir" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:sz-ok/submodule_subdir.git
git push -u origin main
这样,我们已经有了父项目submodule_main与子项目submodule_subdir,然后我们可以进行添加子模块的操作。
添加子模块:
git clone git@github.com:sz-ok/submodule_main.git # clone 父项目
cd submodule_main/ # 进入父项目目录
git submodule add git@github.com:sz-ok/submodule_subdir.git #在主项目中添加子项目
这时项目中会多出submodule_subdir文件夹,是独立的子项目。整个项目包括了多个.git仓,且主项目目录下会多一个.gitmodules文件。
然后,在主项目目录下查看状态:
submodule_main$ git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitmodules
new file: submodule_subdir
可见在添加子模块后,主项目下需要将子项目信息提交一次,提交后,在主项目仓库中,会显示出子模块文件夹,并附带其所在仓库的版本号,如:submodule_subdir @ abcd1234。
git add -u
git commit -m "add submodule"
git push # 因为在建库时用了git push -u 所以后面push时可以直接git push
最终形成的目录结构如下(以下展示局部):
submodule_main$ tree -a -L 3
submodule_main
├── .git # 父项目仓库
│ ├── branches
│ ├── config
│ ├── description
│ ├── HEAD
│ ├── hooks
│ ├── index
│ ├── info
│ ├── logs
│ ├── modules # 管理子项目的modules
│ │ └── submodule_subdir
│ ├── objects
│ ├── packed-refs
│ └── refs
├── .gitmodules # 管理子项目的modules
├── README.md
└── submodule_subdir
├── .git # 子项目仓库
└── README.md
其中.gitmodules用来管理子模块,内容如下:
submodule_main$ cat .gitmodules
[submodule "submodule_subdir"]
path = submodule_subdir
url = git@github.com:sz-ok/submodule_subdir.git
1.2 clone已经存在的多仓库项目
如果我们需要从库上clone一个多仓库的项目。
方法1:
git clone git@github.com:sz-ok/submodule_main.git # 单独使用 git clone 命令是不会拉取到子项目的代码的
cd submodule_main/
git submodule init # 只用执行一次,后续同步只需执行git submodule update
git submodule update # 更新子模块
这样就可以clone上节多仓库的工程。(不过示例中仅有一个模块,不能充分体现git submodule的优势,如果子模块非常多也是同样操作,不需要一个个pull库,然后组织在一起。)
方法2:
组合命令:
git clone git@github.com:sz-ok/submodule_main.git # 单独使用 git clone 命令是不会拉取到子项目的代码的
cd submodule_main/
git submodule update --init --recursive
方法3:
git clone时带上--recursive参数。
git clone git@github.com:sz-ok/submodule_main.git --recursive # 递归的方式克隆整个项目
2 子模块库修改及提交
由于:父项目git仓库管理父项目内容和子项目信息;子项目git仓库管理子项目内容。
所以:
-
父项目中的内容有改动,还是正常的git add, git commit, git push操作
-
子项目中内容有改动时,同样需要git add, git commit, git push操作,然后父项目也要提交一次改动(因为子项目信息有改动)
父项目通过git diff并不能直接看到子项目的修改,如果需要查看,可在父目录下执行
git diff --submodule
3 模块的删除
删除子模块稍微比较复杂,还是以上述例子为例。
git rm --cached submodule_subdir
rm -rf submodule_subdir
vi .gitmodules # 只删除此模块信息
vim .git/config
进行上述操作后,需要在父目录下进行一次提交。
4 模块的分支管理
当clone包换submodule的项目时,主项目获取到的是子项目的commit id,所以clone之后子项目不在任何分支上。主项目执行 git submodule update 也不会更新,此时需要从主项目主动进入子项目执行 git pull 主动拉取新版代码,然后提交,更新子项目的commit id。如果要在主项目开发子模块,建议将子项目切到master分支进行提交。当主项目 clone 后,也可以使用 foreach 命令批量切换到 master 分支进行更新。
若一个项目中有多个子模块需要执行相同的操作,每次切换到对应的目录挨个执行效率太低,此时可以使用 git submodule foreach
类似:
git submodule foreach git checkout master
git submodule foreach git pull
参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!