'git submodule init'的意义是什么?


72

背景

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

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中弃用而不会造成任何损害的残骸。

以下哪项是正确的?

Answers:


59

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


追加了两个工作流程演示。

工作流程1:子模块是多个项目使用的库。

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

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

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

并且其结构的表面如下。

在此处输入图片说明

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

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

在此处输入图片说明

回到子模块工作流程,.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


感谢您指出git submodule init在这种情况下可能会有所帮助。我还没有尝试过,但是对于让我更广泛地考虑git子模块工作流程的问题,您的回答是正确的:)您介意添加一个代码块来说明您暗示的工作流程吗?我认为这将为社区带来更有价值的答案。再次感谢:)

感谢您纠正我的英语。我添加了两个工作流程。我不确定这对某人有帮助。
Nigiri

如果您还有其他子模块,并且只想初始化+更新某些特定的子模块,则工作流程将变为:[git子模块init-./lib1 ./lib2]和[git子模块更新--remote --recursive-./lib1。 / lib2]。另外,您可以在更新命令中使用[--merge]或[--rebase],但请先阅读它们的内容,因为如果HEAD在更新期间不在正确的分支上,它们可以避免历史记录头分离,否则可能会破坏其历史记录。现在,您可以使用[git子模块foreach“ git checkout master && git pull”]修复分离的头部状态(子模块非常有趣且易于使用xD)
FocusedWolf

20

读取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

1
例如,当子模块很大时,由于其他原因,您已经在本地获取了该子模块。 git config -f .gitmodules submodule.biglib.url=/path/to/it比编辑文件git submodule update --init更容易,并且对默认设置满意的情况比两步操作更容易。
jthill
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.