如何保证 git 子模块检查特定标签?

Isa*_*aac 4 tags git git-submodules

这是我的情况:

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

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

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

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

tor*_*rek 14

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

\n

就 Git 而言,子模块要点分离的 HEAD 模式。超级项目 Git 决定使用哪个提交。超级项目 commit\xe2\x80\x94 现在实际签出,在超级项目\xe2\x80\x94 中列出了每个子模块的原始提交哈希 ID。然后超级项目 Git 会执行以下操作:

\n
git -C path/to/submodule checkout <hash>\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

这意味着我们可以使用我们无法控制的子模块。我们无法在该子模块中创建新的标签名称,但我们可以进行git checkout任何我们喜欢的提交,然后在超级项目中创建一个新的提交,其中表示. 然后我们就完成了。check out commit hash in path/to/submodule

\n

唯一剩下的问题实际上是这个:

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

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

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

    \n
  • \n
\n

答案是:只需检查子项目中所需的提交即可,例如:

\n
git -C sub/mod checkout v3.1415926\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
git add sub/mod\n
Run Code Online (Sandbox Code Playgroud)\n

那么这一切到底是什么呢?

\n
\n
git submodule update --init --recursive --remote\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这里的参数--remote意味着:我在某处存储了一些名称。对于每个子模块,执行git -C path/to/submodule fetch\xe2\x80\x94 ,这是该部分的第一部分--remote\xe2\x80\x94 ,然后git -C path/to/submodule checkoutname 使用存储的name. 这是该的第二部分--remote递归地执行此操作,即,如果子模块本身是更多子模块的超级项目,则也对这些子模块执行此操作。 这就是--recursive部分。

\n

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

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

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

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

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

\n

这一切都非常复杂,也相当微妙,因为例如,有人很容易自行设置.git/config并忘记更新。.gitmodules那么你,如果你不是这个人,就会得到错误的名字!出于这个原因,如果您无论如何都会选择哪个子模块进行哪个提交,那么我通常建议您手动完成这一切。

\n