Git submodule

面对比较复杂的项目,我们有可能会将代码根据功能拆解成不同的子模块。主项目对子模块有依赖关系,却又并不关心子模块的内部开发流程细节。
submodule允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。

一、创建 submodule

首先创建有两个项目,同时上传至git并保持同步:main-project(主) 和 sub-project(子)
其中 project-main 的远程仓库地址为 http://xxxx/main-project.git,而 project-sub-1 的远程仓库地址为http://xxxx/sub-project.git
在main-project 中添加 sub-project ,而又保持 sub-project 自身独立的版本控制。

使用 git submodule add 命令可以在项目中创建一个submodule 。
从主项目文件夹中进入git

$ git submodule add http://xxxx/sub-project.git
Cloning into 'D:/project/main-project/sub-project'...
remote: Counting objects: 60, done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 60 (delta 14), reused 0 (delta 0)
Unpacking objects: 100% (60/60), done.
warning: LF will be replaced by CRLF in .gitmodules.
The file will have its original line endings in your working directory

默认情况下,子模块会将submodule放到一个与仓库同名的目录中, 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径
此时其会在main-project文件夹下创建sub-project submodule,如下图

Git submodule_第1张图片

运行 git status查看目前状态

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged ..." to unstage)
        modified:   .gitmodules
        new file:   sub-project

Git submodule_第2张图片

此处的 .gitmodules 文件,该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射关系,如果有多个子模块,该文件中就会有多条记录。

运行git diff --cached sub-project/ 查看不同

$ git diff --cached sub-project/
diff --git a/sub-project b/sub-project
new file mode 160000
index 0000000..b25121d
--- /dev/null
+++ b/sub-project
@@ -0,0 +1 @@
+Subproject commit b25121d683f0e47b798fa095579d9fa6761ee698

此处记录的 160000 模式, 是 Git 中的一种特殊模式,它本质上意味着你是将一次提交记作一项目录记录的,而非将它记录成一个子目录或者一个文件。

最后我们提交它,至此我们已经添加了一个submodule(sub-project),其中在main-project中的.gitmodules 文件中保存了之间的映射关系,除此之外,此时在 .git/config 文件中也会多出一些信息,在 .git/modules 文件夹下也会多出一份内容,如下图。

Git submodule_第3张图片

二、 submodule内容的更新

当sub-projcet子项目在其他人员修改更新后,main-project项目如何同步更新

首先我们在sub-project独立项目上修改代码后提交

之后我们在main-project和main-project的submodule(sub-project)上查看更新状态,发现并没有同步内容信息

Git submodule_第4张图片

这还是说明在main-project中保存的submodule中只是sub-project当时的一个版本,最新的版本内容并不会根据sub-project的同步而同步。

主项目可以使用 git submodule update 更新子模块的代码,但那是指 当前主项目文件夹下的子模块目录内容与当前主项目记录的子模块版本不一致时,会参考后者进行更新,而我们在sub-project独立项目上修改代码后提交主项目并不知晓。

此时我们进入submodule(sub-project)文件路径下
拉取submodule的master分支代码 git pull origin master

EDZ@▒▒ƽ̨▒▒ҵ▒▒-▒▒ʫ▒▒ MINGW64 /d/project/main-project/sub-project (master)
$ git pull origin master
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 2), reused 4 (delta 0)
Unpacking objects: 100% (6/6), done.
From http://xxxx/sub-project
 * branch            master     -> FETCH_HEAD
   b25121d..b861fae  master     -> origin/master
Updating b25121d..b861fae
Fast-forward
 src/main/java/Sub.java | 2 ++
 1 file changed, 2 insertions(+)

同时,我们可以看到main-project有了更新内容信息

Git submodule_第5张图片

如果不想在子目录中手动抓取与合并,那么还有种更容易的方式。 运行 git submodule update --remote,Git 将会进入子模块然后抓取并更新。

EDZ@▒▒ƽ̨▒▒ҵ▒▒-▒▒ʫ▒▒ MINGW64 /d/project/main-project (master)
$ git submodule update --remote
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From http://xxxx/sub-project
   b861fae..6e3c1d6  master     -> origin/master
Submodule path 'sub-project': checked out '6e3c1d61b4d8878d791b95ab9531ffc5ea30f98c'

当运行 git submodule update --remote 时,Git默认会尝试更新所有子模块, 所以如果有很多子模块的话,也可以传递想要更新的子模块的名字。

至此,submodule内容的更新就可以实现

你可能感兴趣的:(git)