Git Submodule项目子模块管理

2022-11-30 11:13:18 浏览数 (1)

模块化与组件化

最近一直在研究客户端的组件化/模块化问题,除了将项目拆分为多个小的子模块,还会涉及到多个子模块管理的问题。下面说一些在模块化开发中的一些基本知识。

一个完整的模块化大型项目,从低到高依次是基础层、 业务层和宿主层,可以根据项目的规模和开发人员的数量拆分成多个子工程协同开发。

宿主层

宿主层位于最上层, 主要作用是作为一个 App 壳, 将需要的模块组装成一个完整的 App, 这一层可以管理整个 App 的生命周期(比如 Application 的初始化和各种组件以及三方库的初始化)。

基础层

业务层位于中层, 里面主要是根据业务需求和应用场景拆分过后的业务模块, 每个模块之间互不依赖, 但又可以相互交互, 比如一个电商App由 搜索、订单、购物车、支付等业务模块组成,且模块之间可以相互调用。

说明:每个业务模块都可以拥有自己独有的 SDK 依赖和自己独有的 UI 资源 (如果是其他业务模块都可以通用的 SDK 依赖 和 UI 资源 就可以将它们抽离到 基础 SDK(CommonSDK 和 UI 组件(CommonRes ) 中。

业务层

基础层位于最底层, 里面又包括 核心基础业务模块、公共服务模块、 基础 SDK 模块, 核心基础业务模块 和 公共服务模块 主要为业务层的每个模块服务, 基础 SDK 模块 含有各种功能强大的团队自行封装的 SDK 以及第三方 SDK, 为整个平台的基础设施建设提供动力。

Git Submodule

Git Submodule 允许一个git仓库,作为另一个git仓库的子目录,并且保持父项目和子项目相互独立。

常用命令

git submodule涉及的常用功能有:

  • git clone <repository> –recursive :递归的方式克隆整个项目
  • git submodule add <repository> <path> :添加子模块
  • git submodule init :初始化子模块
  • git submodule update :更新子模块
  • git submodule foreach git pull: 拉取所有子模块

使用

创建带子模块的项目

例如,现在我们要创建一个如下结构的项目。

代码语言:javascript复制
project
  |--moduleA
  |--readme.txt

依次使用下面的命令,创建project版本库,并提交readme.txt文件。

代码语言:javascript复制
git init --bare project.git
git clone project.git project1
cd project1
echo "This is a project." > readme.txt
git add .
git commit -m "add readme.txt"
git push origin master
cd ..

然后,创建moduleA版本库,并提交a.txt文件。

代码语言:javascript复制
git init --bare moduleA.git
git clone moduleA.git moduleA1
cd moduleA1
echo "This is a submodule." > a.txt
git add .
git commit -m "add a.txt"
git push origin master
cd ..

在project项目中引入子模块moduleA,并提交子模块信息。

代码语言:javascript复制
cd project1
git submodule add ../moduleA.git moduleA
git status
git diff
git add .
git commit -m "add submodule"
git push origin master
cd ..

使用命令git status可以看到多了两个需要提交的文件,其中.gitmodules指定submodule的主要信息,包括子模块的路径和地址信息,moduleA指定了子模块的commit id,使用git diff可以看到这两项的内容。

需要注意的是,父项目的git并不会记录submodule的文件变动,它是按照commit id指定submodule的git header,所以.gitmodules和moduleA这两项是需要提交到父项目的远程仓库的。

代码语言:javascript复制
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    new file:   .gitmodules
    new file:   moduleA

克隆带子模块的版本库

方法一

先clone父项目,再初始化submodule,最后更新submodule,初始化只需要做一次,之后每次只需要直接update就可以了,需要注意submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。

代码语言:javascript复制
git clone project.git project2
cd project2
git submodule init
git submodule update
cd ..

方法二

采用递归参数–recursive,需要注意同样submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。例如:

代码语言:javascript复制
git clone project.git project3 --recursive

修改子模块

修改子模块之后只对子模块的版本库产生影响,对父项目的版本库不会产生任何影响,如果父项目需要用到最新的子模块代码,我们需要更新父项目中submodule commit id,默认可以使用git status就可以看到父项目中submodule commit id已经改变了,我们只需要再次提交就可以了。

代码语言:javascript复制
cd project1/moduleA
git branch
echo "This is a submodule." > b.txt
git add .
git commit -m "add b.txt"
git push origin master
cd ..
git status
git diff
git add .
git commit -m "update submodule add b.txt"
git push origin master
cd ..

更新子模块

更新子模块的时候要注意子模块的分支默认是不是master分支。

方法一

先pull父项目,然后执行git submodule update,注意moduleA的分支始终不是master。

代码语言:javascript复制
cd project2
git pull
git submodule update
cd ..

方法二

先进入子模块,然后切换到需要的分支,这里是master分支,然后对子模块pull,这种方法会改变子模块的分支。

代码语言:javascript复制
cd project3/moduleA
git checkout master
cd ..
git submodule foreach git pull
cd ..

删除子模块

删除子模块会涉及到以下几个步骤:

  1. 删除.gitsubmodule里相关部分;
  2. 删除.git/config 文件里相关字段;
  3. 删除子仓库目录。

网上有好多使用的是下面的这种方法:

代码语言:javascript复制
git rm --cached moduleA
rm -rf moduleA
rm .gitmodules
vim .git/config

然后提交到远程服务器:

代码语言:javascript复制
git add .
git commit -m "remove submodule"

0 人点赞