【问题标题】:What is the point of 'git submodule init'?“git submodule init”有什么意义?
【发布时间】:2017-11-06 01:52:15
【问题描述】:

背景

要填充存储库的子模块,一个typically invokes

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

以下哪些是正确的?

【问题讨论】:

    标签: git git-submodules rationale


    【解决方案1】:

    假设存储库有 10 个子模块,而您只对其中的两个子模块感兴趣。在这种情况下,您可能希望不时从远程存储库中仅从这两个子模块获取更新。 git init 对此非常有效,因为一旦您对这两个子模块执行命令 git initgit 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
    

    您想重构引用 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”。

    此时,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
    

    这次你想重构主项目的共享目录中的一些代码,你知道只有子项目1和子项目2引用了共享代码,这意味着你不需要克隆和签出子项目3和子项目4。所以你只需运行下面的命令。

    git submodule init sub-project1 sub-project2
    

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

    git submodule update
    

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

    【讨论】:

    • 感谢您指出 git submodule init 在此用例中可能会有所帮助。我还没有尝试过,但赞成你的回答让我更广泛地思考 git 子模块工作流程:) 你介意添加一个代码块来说明你暗示的工作流程吗?我认为这将为社区提供更有价值的答案。再次感谢:)
    • 感谢您纠正我的英语。我添加了两个工作流程。不过,我不确定这对某人有帮助。
    • 如果您有其他子模块并且只想初始化 + 更新一些特定的子模块,那么工作流程变为:[git submodule init -- ./lib1 ./lib2] 和 [git submodule update --remote - -递归——./lib1 ./lib2]。您也可以将 [--merge] 或 [--rebase] 与 update 命令一起使用,但首先阅读它们的作用,因为如果 HEAD 在更新期间不在正确的分支上,它们可以避免分离的头检出,但可能会破坏其历史记录.现在,您可以使用 [git submodule foreach "git checkout master && git pull"] 修复分离的头部状态(子模块非常有趣且易于使用 xD)
    【解决方案2】:

    阅读git submoduledocumentation一个用例,表面上证明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
    

    【讨论】:

    • 例如,当子模块很大并且由于其他原因您已经在本地获得它时。 git config -f .gitmodules submodule.biglib.url=/path/to/it 比编辑文件更容易,git submodule update --init 当您对默认设置感到满意时,比两步更容易。
    猜你喜欢
    • 2017-02-07
    • 2023-03-30
    • 2018-01-31
    • 2022-12-08
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2023-02-26
    • 2014-03-18
    相关资源
    最近更新 更多