一文看懂Git submodule

背景 有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又...

背景

有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。

我们举一个例子。 假设你正在开发一个网站然后创建了 Atom 订阅。 你决定使用一个库,而不是写自己的 Atom 生成代码。 你可能不得不通过 CPAN 安装或 Ruby gem 来包含共享库中的代码,或者将源代码直接拷贝到自己的项目中。 如果将这个库包含进来,那么无论用何种方式都很难定制它,部署则更加困难,因为你必须确保每一个客户端都包含该库。 如果将代码复制到自己的项目中,那么你做的任何自定义修改都会使合并上游的改动变得困难。

Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。


案例

我们假设这样一种情况,本地的测试项目结构如下:

attachments-2024-02-eXfJoYT165be82b7c62ff,png

其中 LearnLocal 是主项目,对应的远程项目路径为:ssh://[ssh]/learn.git

LearnSubLocal是子项目,对应的远程项目路径为:ssh://[ssh]/learnSub.git

如果我们直接在 LearnLocal 文件夹下执行:git add LearnSubLocal/ 会发生什么?

 $ git add LearnSubLocal/
warning: adding embedded git repository: LearnSubLocal
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint:
hint:   git submodule add <url> LearnSubLocal
hint:
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint:
hint:   git rm --cached LearnSubLocal
hint:
hint: See "git help submodule" for more information.

在终端里多了许多平常没见到的提示,比如:

warning: adding embedded git repository: LearnSubLocal

(警告:正在添加嵌入的git项目:LearnSubLocal)

这是因为 LearnSubLocal 实际上关联了另一个 git 工作区,我们可以在这个文件夹下看到 .git 文件夹,代表这是一个git工作区。

attachments-2024-02-oZbSpG7B65be82cf23d79,png

现在我们暂且不关心这个警告,直接继续提交,并且推送到远端,会发生什么呢?

git commit -m "Add LearnSubLocal"

git push origin master

在远程网页看到,工程已经提交上去了

attachments-2024-02-Y7k6qzhd65be82df6bd34,png

但是会发现这个文件夹点击不了,也就是说在远程没办法看到子项目的内容。

我们尝试性在本地clone这个仓库,得到的结果是:

attachments-2024-02-5Xm9g68165be835b224b0,png

发现LearnSubLocal仍旧是空的,也就是说在已有的git工作区提交另一个子git工作区失效,只能提交这个文件夹,内容却提交不了。

如果想要提交这个文件夹及其里面的内容,有如下三种办法

  1. 删除LearnSubLocal下面的.git文件夹

2. 如果想要保留 .git 文件夹,一种取巧的办法是将其压缩为 zip文件,再上传(还是要删除.git文件夹)

3. submodule 功能(今天的主角)


submodule

现在我们创建一个只有主模块的文件夹:Learn.git

这个文件夹下面只有 README.md 文件

attachments-2024-02-sVa8OWXx65be836f32d25,png

执行指令:

$ git submodule add ssh://[ssh]/learnsub.git

将learnsub.git注册和添加为Learn.git的模块

这个指令会在运行 git 命令的文件夹下新建一个同名文件夹,如果你想命名到自定义路径可以按照这样的指令结构修改:git submodule url path

attachments-2024-02-fRpk42W265be83aa9f06a,png

指令执行的结果是:添加了learnsub文件夹,以及添加了.gitmodules

learnsub我们知道是什么,.gitmodules呢?

看看便知:

$ vim .gitmodules

attachments-2024-02-0x4n4UgX65be83c0962e5,png

这个文件建立了子模块文件夹和url的映射关系,如果你添加了多个自模块,这里会有多个映射关系。

查看下当前工作环境

$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file:   .gitmodules
new file:   learnsub

再次提交:

$ git add ./
$ git commit -m "Add submodule"
[master 2f86134] Add submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 learnsub
$ git push origin master

看看远程仓库变成什么样了?

attachments-2024-02-gvOwcZKX65be83d47de1c,png

这时候点击 learnsub 文件夹,他会根据.gitmodules的映射关系跳转到对应的子模块仓库。

attachments-2024-02-gUwKh1hG65be83ea722b1,png

现在推送到远端的操作完成了,主模块也建立了子模块文件夹与url的映射关系。

接着我们来试试从远端clone:

$ git clone ssh://[ssh]/learn.git

看起来一切安好

attachments-2024-02-KPyOyvkj65be83fe0c983,png

点进learnsub里面看看:

诶,为什么文件夹里面是空的?

attachments-2024-02-YAcvJlUU65be8414b45cf,png

根据官网的介绍,你必须运行两个命令:

git submodule init 用来初始化本地配置文件,
git submodule update 则从该项目中抓取所有数据并检出父项目中列出的合适的提交。

也可以用下面的指令一步到位:

git submodule update --init --recursive

用用看:

$ git submodule init
Submodule 'learnsub' (ssh://[ssh]/learnsub.git) registered for path 'learnsub'
$ git submodule update
Cloning into 'C:/Users/[path]/learn/learnsub'...
Submodule path 'learnsub': checked out 'fb2971eb3355cef677448d93xxxxxxxxcc1'

搞定了!!!

attachments-2024-02-rx2bQyvI65be84279fd27,png

恭喜你,可以接着愉快的开发了(秃头了)。


总结

  1. git无法直接提交带有.git文件夹的子工作区
  2. 如果想要提交,可以把.git文件夹删除
  3. 更好的办法是使用submodule将其注册为子模块
  • 发表于 2024-02-04 02:21
  • 阅读 ( 448 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
shitian
shitian

662 篇文章

作家榜 »

  1. shitian 662 文章
  2. 石天 437 文章
  3. 每天惠23 33 文章
  4. 小A 29 文章