聊聊 Git SubModule(子模块)

2024-02-19 17:28
文章标签 模块 聊聊 git submodule

本文主要是介绍聊聊 Git SubModule(子模块),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

比如在公司不同开发团队中,有一个基础共享库,同时被多个项目调用。若要保证基础共享库的动态更新,那么就需要把共享库独立为一个代码库,但是分别把共享库中的文件拷贝到各自的项目中会造成冗余,而且再次更新共享库就会在不同项目下更新,会比较麻烦。

利用子模块可以作为解决该类问题的一种方案,子模块允许将一个Git仓库作为另一个Git仓库的子目录,并且可以独立地管理这个子仓库的版本,而且还能保持提交的独立性。

下面就通过实操来具体谈谈 Git submodule

一、什么是Git Submodule

Git Submodule 是Git版本控制系统中的一种机制,用于在一个Git仓库中包含另一个Git仓库。它允许将一个Git仓库作为另一个Git仓库的子目录,并且可以独立地管理这个子仓库的版本,同时还保持提交的独立。
image.png
Submodule的作用在于,它允许你在一个项目中使用其他项目的特定版本,而无需将整个子项目的代码复制到主项目中。这对于依赖管理和代码复用非常有用。

二、使用 Git Submodule

1 创建和初始化仓库

  • 初始化主库和子模块库

我采用的是 Gitee 来进行本次实操,首先在 Gitee 中创建一个主库 GitSubmoduleDemo,两个子模块库 ModuleAModuleB:
image.png
先将主库 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:   .gitmodulesnew file:   ModuleAnew file:   ModuleB

发现有新的文件在主库中,分别是 .gitmodules文件,ModuleAModuleB目录

1.1 .gitmodules文件

首先看一下 .gitmodules配置文件,它保存了远程仓库 url 与本地仓库 url 路径的映射:

[submodule "ModuleA"]path = ModuleAurl = ../module-a.git
[submodule "ModuleB"]path = ModuleBurl = ../module-b.git

每条记录对应一个子模块信息,path 和 url 对应远程仓库 url 和本地仓库路径

1.2 主库中的子模块

接着提交当前主库中出现的文件和目录:

//暂存
$ git add .
//提交
$ git commit -m "ModuleA and ModuleB submodule commit"
[master 2dcfefd] ModuleA and ModuleB submodule commit3 files changed, 8 insertions(+)create mode 100644 .gitmodulescreate mode 160000 ModuleAcreate mode 160000 ModuleB

发现ModuleAModuleB目录的模式编码为 160000
在之前讲解 index文件提到过,模式 160000是引用其他 Git 仓库的特殊文件类型,它允许将一个 Git 仓库作为另一个仓库的子目录进行管理。具体可以看这篇文章Git暂存区机制详解
所以此时主库中只是存储了子模块的引用,也就是一次的提交记录。而不是其他的文件或者目录。最后将主库中的修改进行推送:

$ git push origin master

image.png
发现在主库中ModuleAModuleB确实是以引用的形式存储的。

2 更新和同步子模块

那么如何将子模块的修改更新到主仓库中呢?这又分两种情况:

  • 在子模块所在的仓库中修改代码后提交,然后在主仓库中拉取更新
  • 在主仓库中修改子模块代码后提交远程仓库,然后在子模块仓库中拉取更新

2.1 主仓库更新子模块仓库中的修改

首先在子模块仓库 ModuleA 中新增一个文件,并提交到 ModuleA 的远程仓库中:

$ echo "updateModuleA-1">updateModuleA-1.txt
$ git add .
$ git commit -m "update ModuleA"
$ git push

image.png
此时子模块仓库中的 commit ID 值为 6026b48,再来看一下主仓库中的子模块的 Commit ID 值
image.png
发现此时主仓库的 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 保持一致:

image.png

2.2 子模块仓库更新主仓库中子模块代码的修改提交

首先在主仓库的子模块目录下修改代码:

//在主仓库中进入子模块ModuleA目录
$ cd ModuleA
//修改文件和提交和普通Git仓库提交流程一致:
//1.创建文件并提交
$ echo "ModuleA">updateModuleA.txt
$ git add .
$ git commit -m "update ModuleA"
//2.推送到远程ModuleA仓库
$ git push

发现远程子模块仓库也同步完成:

image.png

接着需要将主仓库中的子模块 ModuleA 的变化同步到远程主仓库中具体的操作和上一节主仓库更新子模块仓库中的修改类似,用 add 和 commit 方式提交主仓库的更新,这个时候就完成了子模块和主仓库代码一致。

$ cd ..
$ git add .
$ git commit -m "update ModuleA"
$ git push

在实际的 IDE 环境中,只需要在子模块目录下进行代码修改:

image.png
然后在提交时先更新子模块 ModuleB 的远程仓库:
image.png
然后再同步远程主仓库中的 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 的更新变化:
image.png
接着推送到远程主仓库即可完成主仓库和子模块仓库的更新

三、总结

本文通过实践介绍子模块:

  • 包括子模块的初始化,如何使用 git submodule add 命令在主仓库添加子模块
  • 如何在子模块和主仓库之间的更新和同步

子模块主要有以下应用场景

  • 不同项目间需要共享同一个公共代码,如基础类库或工具包;
  • 较大的项目需要拆分成多个子项目进行开发,通过子模块控制依赖关系;
  • 第三方开源库或组件的本地开发与项目进行绑定;
  • 需要隔离成组和组件版本的同时利用依赖关系,如微服务架构下的服务与组件;
  • 子项目有较强的独立性同时也存在一定的耦合关系,通过子模块进行管理。

同时从上面的时间可以看到,子模块和主仓库之间的同步比较复杂,维护成本高,子模块与主项目需要进行紧密的协调管理,否则很容易导致不同步的情况出现。在使用中要结合实际情况下操作,简单的项目就不要用子模块,采用分支管理可能更合适。

参考资料

公共模块管理之 Git Submodule 使用总结
Git - 子模块
《Git 权威指南 蒋鑫著》

这篇关于聊聊 Git SubModule(子模块)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/725394

相关文章

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

python中time模块的常用方法及应用详解

《python中time模块的常用方法及应用详解》在Python开发中,时间处理是绕不开的刚需场景,从性能计时到定时任务,从日志记录到数据同步,时间模块始终是开发者最得力的工具之一,本文将通过真实案例... 目录一、时间基石:time.time()典型场景:程序性能分析进阶技巧:结合上下文管理器实现自动计时

Git如何修改已提交人的用户名和邮箱

《Git如何修改已提交人的用户名和邮箱》文章介绍了如何修改Git已提交人的用户名和邮箱,包括注意事项和具体步骤,确保操作正确无误... 目录git修改已提交人的用户名和邮箱前言第一步第二步总结git修改已提交人的用户名和邮箱前言需注意以下两点内容:需要在顶层目录下(php就是 .git 文件夹所在的目

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模