94

背景

要填充存储库的子模块,通常会调用

git submodule init
git submodule update

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

那有什么意义呢?

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

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

问题

任何一个:

  • 有一些git submodule init我不知道的用例(在这种情况下,请赐教!);要不然
  • git submodule init是粗鲁的,可以在 Git 中弃用而不会造成任何伤害。

以下哪一个是真的?

4

2 回答 2

80

假设存储库有 10 个子模块,而您只对其中的两个子模块感兴趣。在这种情况下,您可能希望不时从远程存储库中仅从这两个子模块获取更新。git init对此效果很好,因为一旦您git init为这两个子模块执行命令,git submodule update --remote仅适用于它们。


附加了两个工作流演示。

Workflow1:子模块是多个项目使用的库。

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

您刚刚克隆了“我的项目”。

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

它的结构表面如下图。

在此处输入图像描述

.gitmodules 的内容

[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

您想重构code1.js引用 lib1 和 lib2 的代码,这意味着您不需要克隆和签出 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”。

此时,lib1 和 lib2 目录为空。您可以使用一个命令克隆和签出 lib1 和 lib2:

git submodule update

现在您可以在code1.js没有导入错误的情况下进行重构。

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

git submodule update --remote

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

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

我是这个的粉丝。

您克隆“主项目”。

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

它的结构表面如下图。

在此处输入图像描述

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

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

在此处输入图像描述

回到子模块工作流程,.gitmodules 的内容如下。

[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

这次你想重构主项目的共享目录中的一些代码,你知道只有 sub-project1 和 sub-project2 引用了共享代码,这意味着你不需要克隆和签出 sub-project3 和 sub-项目4。因此,您只需运行以下命令。

git submodule init sub-project1 sub-project2

就像我在工作流 1 中提到的那样,您需要运行下面的命令来克隆和签出它们。

git submodule update

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

于 2017-10-05T09:44:56.627 回答
25

阅读git submodule 文档,有一个用例表面上证明了git submodule init作为独立命令的存在是合理的。

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

git submodule init
vim .git/config # Alter submodule URL as desired, without changing .gitmodules
                # or polluting history.
git submodule update
于 2017-06-05T10:53:12.513 回答