【问题标题】:How to guarantee git submodule is checking out a specific tag?如何保证 git submodule 正在检查特定标签?
【发布时间】:2021-06-01 20:16:45
【问题描述】:

这是我的情况:

我们正在尝试将我们正在处理的项目转换为使用子模块。由于我们之前进行了测试,因此子模块只是指开发分支。现在我想将所有模块转换为从开发分支指向主分支上的特定发布标签。其中一个模块还需要更改远程 URL,因此我按照these 说明修改 .gitmodule 文件并更新远程 URL 和分支;我什至执行了说我需要从根级目录git submodule update --init --recursive --remote 的评论。然后我按照these 的说明,进入每个子模块,检查每个子模块中各自的发布标签。

这似乎工作正常,但是当我运行git status 时,它抱怨有一个分离的头(我想这是意料之中的,因为我检查了分支上的标签而不是实际的分支本身)。但是,我随后 git added 所有子模块并提交到我的本地仓库但尚未推送,因为我实际上不确定子模块是否指向所需的标签。

那么,我如何验证当同事克隆这个项目时,它会以我希望设置的发布标签所指的状态拉取子模块?我尝试查看 .gitmodule 文件,希望看到“标签”值,但什么也没有。我还检查了各个 .git/module/sub_module_path/config 文件,在这里也没有看到任何内容。

我如何确定子模块将被克隆到所需的标签?

【问题讨论】:

    标签: git tags git-submodules


    【解决方案1】:

    子模块从不“指向标签”(这通常是不可能的,正如您所发现的:签出标签名称只会导致 HEAD 分离)。请注意,标签名称只是一个特定提交的人类可读名称。任何时候使用标签,可以将标签解析为正确的提交哈希 ID,然后直接使用哈希 ID。

    子模块的point,就 Git 而言,是 处于分离 HEAD 模式。超级项目 Git 说明了使用哪个提交。超级项目提交——现在在超级项目中实际签出的提交——列出了每个子模块的原始提交哈希 ID。超级项目 Git 然后执行:

    git -C path/to/submodule checkout <hash>
    

    使用超级项目提供的哈希。所以这与标签“一样好”:我们只是将哈希 ID 存储在超级项目的 commit 中,而不是将其存储在子模块。

    这意味着我们可以使用我们无法控制的子模块。我们不能在那个子模块中创建新的标签名称,但是我们可以git checkout任何我们喜欢的提交,然后在超级项目中创建一个新的commit,上面写着@987654323 @。然后我们就完成了。

    剩下的唯一问题,真的,就是这个:

    • 好的,所以我们有一个超级项目,以及一些提交 a123456,当该提交被签出并运行 git submodule update --init 时,签出该标签。

    • 但现在我们要在超级项目中进行一些新的和改进的提交。

    • 在这些新的和改进的提交中的至少一个(例如,下一个版本)中,我们希望一个特定的子模块 sub/mod 位于 v3.1415926(即提交 feedc0ffee),而不是旧的和糟糕的v1.4142136(提交badcab1e)。那么我们如何确保超级项目中的这些新提交使用哈希 ID feedc0ffee

    答案是:只需在子项目中签出所需的提交in,例如:

    git -C sub/mod checkout v3.1415926
    

    然后在超级项目中运行git add

    git add sub/mod
    

    那么这一切是什么?

    git submodule update --init --recursive --remote
    

    这里的--remote 参数意味着:我有一些名字存储在某个地方。对于每个子模块,执行git -C path/to/submodule fetch——这是--remote 部分的第一部分——然后是git -C path/to/submodule checkout名称​​存储的name。这是--remote 的第二部分。 递归地执行此操作,即,如果子模块本身是更多子模块的超级项目,那么也对这些子模块执行此操作。这是--recursive 部分。

    这是一个非常强大的东西,有多个活动部件:

    • name 存储在哪里?您如何知道每个子模块使用的名称?
    • 谁在控制 name 如何解析为哈希 ID?我们在子模块中运行git fetchin,所以它是子模块的远程!
    • 我们将获得哪些哈希 ID?这取决于该子模块中更新的git fetch 名称(如果有)。

    这些问题都有答案,但只有“名称存储在哪里”应该(或可以)在这里回答。名称来自:

    • 超级项目的.git/config,如果它设置在那里;或
    • 超级项目的.gitmodules,如果它设置在那里;或
    • master

    除了硬编码的master之外,这些都有更多的控制旋钮:您可以使用git configgit submodule来更新.git/config和/或.gitmodules

    这一切都相当复杂,也相当微妙,因为有人很容易在自己的.git/config 中设置它而忘记更新.gitmodules。那么你,如果你不是这个人,就会得到错误的名字!出于这个原因,我通常建议只手动完成所有操作,如果您是要选择哪个子模块继续哪个提交的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-10
      • 2018-06-07
      • 2023-02-26
      • 2013-12-15
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 2015-08-01
      相关资源
      最近更新 更多