“ git 子模块 init”的意义是什么?

背景资料

To populate a repository's submodules, one 典型的调用:

git submodule init
git submodule update

在这种用法中,git submodule init似乎只做一件事: 用 .gitmodules中已有的信息填充 .git/config

这有什么意义呢?

git submodule update不能简单地使用来自 .gitmodules的信息吗? 这将避免两者:

  • 不必要的命令(git submodule init) ; 以及
  • 不必要的数据复制(.gitmodules内容到 .git/config)。

提问

或者:

  • 有一些我不知道的 git submodule init用例(在这种情况下,请告诉我!) ;
  • git submodule init是可以在 Git 中弃用而不会造成任何伤害的未加工部件。

哪一个是真的?

99151 次浏览

在读取 git submodule 文件时,有一个用例 is,表面上证明了 git submodule init作为一个独立命令的存在。

如果克隆了存储库的用户希望为子模块使用不同于上游存储库指定的 URL,那么该用户可以:

git submodule init
vim .git/config # Alter submodule URL as desired, without changing .gitmodules
# or polluting history.
git submodule update

假设存储库有10个子模块,而您只对其中的两个子模块感兴趣。在这种情况下,您可能希望只从远程存储库中的这两个子模块不时地获得更新。git init可以很好地解决这个问题,因为一旦对这两个子模块执行命令 git initgit submodule update --remote就只应用于它们。


附加了两个工作流演示。

Workflow 1: 子模块是一些项目使用的库。

我认为这是一个常见的用例。

You just cloned "my-project".

git clone https://example.com/demo/my-project

它的结构表面如下。

Enter image description here

Gitmodule 的内容

[submodule "lib1"]
path = lib1
url = https://example.com/demo/lib1
[submodule "lib2"]
path = lib2
url = https://example.com/demo/lib2
[submodule "lib3"]
path = lib3
url = https://example.com/demo/lib3
[submodule "lib4"]
path = lib4
url = https://example.com/demo/lib4

您需要重构引用 lib1和 lib2的代码 code1.js,这意味着您不需要克隆和签出 lib3和 lib4。所以只需运行下面的命令。

git submodule init lib1 lib2

现在让我们看看 .git/config的内容

...
[submodule "lib1"]
active = true
url = https://example.com/demo/lib1
[submodule "lib2"]
active = true
url = https://example.com/demo/lib2

这意味着“准备从 example.com/demo 更新 lib1和 lib2”。

At this point, lib1 and lib2 directories are empty. You can clone and checkout lib1 and lib2 with one command:

git submodule update

现在您可以在不导入错误的情况下重构 code1.js

子模块只是对某些提交的引用。因此,当您想要更新库到新版本时,您必须更新引用。您可以通过以下命令进行操作。

git submodule update --remote

现在您可以看到只初始化所需的子模块是多么有用。

工作流2: 每个子模块都是一个项目,一个大的顶级项目包括它们。

我很喜欢这个。

你克隆了“主项目”。

git clone https://example.com/demo/main-project

它的结构表面如下。

Enter image description here

您可以看到一个名为“ share”的目录。在这个工作流中有一个规则: 如果你想在你的项目中使用 main-project 的共享代码,你必须创建这个项目作为 main-project 的一个子模块。

我喜欢将实体类放在共享目录中,如下所示。

Enter image description here

回到子模块工作流,. gitmodule 的内容如下所示。

[submodule "sub-project1"]
path = sub-project1
url = https://example.com/demo/sub-project1
[submodule "sub-project2"]
path = sub-project2
url = https://example.com/demo/sub-project2
[submodule "sub-project3"]
path = sub-project3
url = https://example.com/demo/sub-project3
[submodule "sub-project4"]
path = sub-project4
url = https://example.com/demo/sub-project4

这一次,您想要在 main-project 的共享目录中重构一些代码,并且您知道只有 sub-project1和 sub-project2引用共享代码,这意味着您不需要克隆和 checkout sub-project3和 sub-project4。所以只需运行下面的命令。

git submodule init sub-project1 sub-project2

正如我在 workflow 1中提到的,您需要运行下面的命令来克隆和签出它们。

git submodule update

在这种情况下,我会做 git submodule update --remote吗?或者我甚至需要初始化和更新子模块来重构共享目录中的代码吗?是的,因为在重构共享代码之后,必须在子模块中运行测试,如果在重构期间子模块的任何更新被提交并推送到远程存储库,那么您需要通过 git submodule update --remote获得它。