git 子模块 submodule

文档

https://git-scm.com/book/zh/v2/Git-工具-子模块

为什么需要子模块

观察项目 https://github.com/develon2015/MultiModule, 它依赖一个子模块 https://github.com/develon2015/MySpringBoot.
如果主项目在开发过程中需要导入该依赖模块, 那么直接通过HTTPS协议克隆该子模块并注册到配置文件:

git submodule add https://github.com/develon2015/MySpringBoot MySpringBoot

下载完成后, 在根项目下将生成一个.gitmodules文件, 同时在MySpringBoot目录下没有.git目录, 而是被初始化在根目录下的.git/modules/MySpringBoot目录下:
取而代之的是一个.git文本文件:

$ cat .gitmodules
[submodule "MySpringBoot"]
        path = MySpringBoot
        url = https://github.com/develon2015/MySpringBoot
$ cat MySpringBoot/.git
gitdir: ../.git/modules/MySpringBoot

这意味着无法提交MySpringBoot项目, 只能在别的目录下克隆MySpringBoot的git协议版本, 修改并提交, 然后回来拉取MySpringBoot:

git submodule update # 下载或更新子模块

显然这只适合大部分模块使用者, 因为对于这些模块的完全开发者来说, 这不方便提交同时开发.

怎解?

我们假设两个项目都是git协议的git项目, 它们都已开发完毕, 正准备提交.
首先按正常流程提交子模块MySpringBoot, 这不会有任何问题.
接下来, 我们回到根项目, 添加跟踪文件:

$ git add MySpringBoot
warning: adding embedded git repository: MySpringBoot 警告:添加嵌入式git存储库:MySpringBoot
hint: You've added another git repository inside your current repository. 提示:您已在当前存储库中添加了另一个git存储库。
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> MySpringBoot
hint:
hint: If you added this path by mistake, you can remove it from the 
hint: index with: 提示:如果您错误地添加了此路径,则可以使用以下方法将其从索引中删除:
hint:
hint:   git rm --cached MySpringBoot
hint:
hint: See "git help submodule" for more information.

git会自动识别, MySpringBoot会被识别为子模块, 只是尚不知道该git项目的URL, 有证:

$ git submodule init
fatal: No url found for submodule path 'MySpringBoot' in .gitmodules

其实, 我们只需要手动创建一个.gitmodules文件并编辑即可:

echo '[submodule "MySpringBoot"]
        path = MySpringBoot
        url = https://github.com/develon2015/MySpringBoot
' >> .gitmodules

接下来追踪.gitmodules, 提交即可, 有证:

$ git submodule init
$ git submodule update
Submodule path 'MySpringBoot': checked out 'f51923868b34a546dec942b8b8bfea4065fc2e95'

克隆含有子模块的git项目

第一种方法, 先直接克隆, 然后初始化本地配置文件后更新子模块:

$ git clone https://github.com/develon2015/MultiModule
Cloning into 'MultiModule'...
$ git submodule init # 初始化本地配置文件
Submodule 'MySpringBoot' (https://github.com/develon2015/MySpringBoot) registered for path 'MySpringBoot'
$ git submodule update # 下载或更新子模块
Submodule path 'MySpringBoot': checked out '89e2ef897b61ec077cfafb2da2b116daf1c97e57'

第二种方法, 克隆项目时传递--recurse-submodules参数:

git clone --recurse-submodules https://github.com/develon2015/MultiModule

注意!

子模块是一种快照模式, 应当十分注意, 避免上传脏快照和没有提交的快照.
脏快照: 提交后有更改
没有提交的快照: 提交后没有push, 最后又--amend之后再提交

$ git diff
diff --git a/MySpringBoot b/MySpringBoot
index d9764bc..f519238 160000
--- a/MySpringBoot
+++ b/MySpringBoot
@@ -1 +1 @@
-Subproject commit d9764bc3955fadae9805dee7e9bf5d96167a4c46 # 没有提交的快照
+Subproject commit f51923868b34a546dec942b8b8bfea4065fc2e95-dirty # 脏快照, 有未提交同时未忽略的文件
  [22:12:22] Administrator@ /cygdrive/d/Code/Projects/MultiModule

$ cd MySpringBoot && git log
commit f51923868b34a546dec942b8b8bfea4065fc2e95 (HEAD -> master, origin/master, origin/HEAD)
Author: develon_cyg <gitee@foxmail.com>
Date:   Sat Aug 22 19:24:01 2020 +0800

    提交API
    JsonConfig
    Logger
    Shell

commit ba7d42d6817ace449a009041c39d5b9f2a1badc6
Author: develon_cyg <gitee@foxmail.com>
Date:   Sat Aug 22 19:21:42 2020 +0800

    修改README.md
    构建DSL从Kotlin修改为Groovy

commit e74763c2d29622a86afa54338ed6b275afc35444
Author: develon2015 <develon@qq.com>
Date:   Tue Aug 18 17:18:03 2020 +0800

    first commit

END

原文地址:https://www.cnblogs.com/develon/p/13547019.html