‘git submodule init’有什么意义?

What is the point of 'git submodule init'?

背景

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

1
2
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中弃用而不会造成任何伤害。

以下哪一项是正确的?


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

附加两个工作流程演示。

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

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

你刚刚克隆了"我的项目"。

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

它的结构表面如下。

Enter image description here

.gitmodules的内容

1
2
3
4
5
6
7
8
9
10
11
12
[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。所以你只需运行以下命令。

1
git submodule init lib1 lib2

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

1
2
3
4
5
6
7
...
[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:

1
git submodule update

现在,您可以重构code1.js而不会导致导入错误。

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

1
git submodule update --remote

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

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

我是这个的粉丝。

你克隆"主项目"。

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

它的结构表面如下。

Enter image description here

您可以看到名为"shared"的目录。此工作流程中有一条规则:如果要在项目中使用main-project的共享代码,则必须将项目创建为main-project的子模块。

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

Enter image description here

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

1
2
3
4
5
6
7
8
9
10
11
12
[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引用共享代码,这意味着你不需要克隆和签出sub-project3和sub- project4。所以你只需运行下面的命令。

1
git submodule init sub-project1 sub-project2

就像我在workflow1中提到的那样,你需要运行下面的命令来克隆和检查它们。

1
git submodule update

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


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

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

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