Git 子模块不断重置为(无分支)
Git submodule keeps resetting to (no branch)
我一遍又一遍地删除并重新添加子模块,但每次我们克隆父存储库时,子模块都位于“(无分支)”
有人可以提供获取子模块的步骤,并正确、明确、毫无疑问地将其锁定在提交上吗?
我采取的步骤:
git submodule add https://bitbucket.org/bla/bla.git my/submodule/path
- 更新子模块以指向分支中的最新提交。提交消息说
From <hash> X months ago Initial commit
To: <hash> 1 day ago <somemessage>
- 推送更改
git clone
在同事的电脑上 git clone https://bitbucket.org/bla/bla.git
该子模块位于我同事计算机上的 (no branch)
上。不应该。它应该在我提交的地方。我错过了什么?
编辑
所以也许“(无分支)”只是误导。在我同事的机器上,它在 初始提交 处检出。这就是核心问题。
在子模块中进行新提交后,您需要在 超级项目 中进行新提交。
正如 所说,这就是子模块的工作方式(尽管人们觉得这很令人沮丧)。不过,这可能有助于理解 为什么 它们以这种方式工作。
请记住,子模块 是 一个(单独的)Git 存储库。也就是说,如果您将存储库 X 作为超级项目并将子模块 Y 作为子模块,则您有两个存储库,X 和 Y。 Git 存储库的核心是 提交 的数据库。为了使提交数据库更有用,存储库还包括一个映射到哈希 ID 的 names 数据库。但是,对于子模块而言,Y 中的名称数据库变得无关紧要!所以我们会假装它不存在。
要使用这个东西,你(或其他人)会将存储库X克隆到副本X2 然后 select 一些在 X2 内提交以检查。您将在 X2 中使用新名称数据库(它独立于 X 中的名称数据库——您的分支名称不是它们的分支名称—但 是 至少 primed 从那个)选择提交哈希 ID。然后你将在 X2 克隆中 运行 git submodule update --init
,它将读取结帐提取的 .gitmodules
文件,以便它知道去哪里克隆 Y 使 Y2 在 X2.
内
将 Y 克隆到 Y2 后,Git 操作 in X2 需要知道要检出 Y2 中的哪个提交。这就是 Y2 名称数据库变得无关紧要的地方。您的 Git 软件在您的 X2 中运行,获取 哈希 ID 以在 Y2[=91= 中使用] 来自 commit in X2。哪个提交?为什么,current 提交,提供 .gitmodules
文件的提交以及首先有一个 Y 的事实。
您在 X 或 X2 中所做的每个提交都带有 正确的 提交在 Y 或 Y2 中查看。因此,如果您曾经向 Y 存储库添加新提交,那么您还必须返回相应的 X 超级项目,运行 git add
从更新的 Y 中获取新的哈希 ID,运行 git commit
在 X 在新的 X 提交中记录新的哈希 ID。这样,这个 X 的任何克隆都将知道获得 new Y 提交。 X 的克隆未使用任何 Y names-database 来获取 Y[=91= 的提交哈希 ID ] 子模块。他们使用提交 within 超级项目 X.
的克隆
换句话说,就是hash ID从哪里来的问题。分支名称输入 branch-and-other-names 数据库中的 Git 克隆,但它们很容易更改。控制子模块的超级项目需要一个严格的、不可更改的标识符,以便提交在子模块中检出——这是一个 哈希 ID,而不是名称。
(人类有时想要比这更大的灵活性,子模块给出的第一个答案是“艰难的 s**t”。但是,Git 现在确实有一些机制来记录分支名称并尝试使用它们。但是向后兼容性意味着这些机制非常笨拙而且非常 user-unfriendly,我不推荐它们,因为它们不仅笨拙,而且很脆弱。知道 原始设计是什么 这就是为什么子模块的行为方式和使用方式。)
好吧,这很尴尬,我们花了太长时间才弄明白,因为我们没有正确阅读,正如你已经从问题中看出的那样。
它在我的机器上运行良好而在我同事的机器上运行良好的原因是因为我使用 https
检查存储库而他使用 SSH
。该子模块包含在 https
url 中,但失败了。我使用了此处建议的相对路径
我一遍又一遍地删除并重新添加子模块,但每次我们克隆父存储库时,子模块都位于“(无分支)” 有人可以提供获取子模块的步骤,并正确、明确、毫无疑问地将其锁定在提交上吗?
我采取的步骤:
git submodule add https://bitbucket.org/bla/bla.git my/submodule/path
- 更新子模块以指向分支中的最新提交。提交消息说
From <hash> X months ago Initial commit
To: <hash> 1 day ago <somemessage>
- 推送更改
git clone
在同事的电脑上git clone https://bitbucket.org/bla/bla.git
该子模块位于我同事计算机上的 (no branch)
上。不应该。它应该在我提交的地方。我错过了什么?
编辑 所以也许“(无分支)”只是误导。在我同事的机器上,它在 初始提交 处检出。这就是核心问题。
在子模块中进行新提交后,您需要在 超级项目 中进行新提交。
正如
请记住,子模块 是 一个(单独的)Git 存储库。也就是说,如果您将存储库 X 作为超级项目并将子模块 Y 作为子模块,则您有两个存储库,X 和 Y。 Git 存储库的核心是 提交 的数据库。为了使提交数据库更有用,存储库还包括一个映射到哈希 ID 的 names 数据库。但是,对于子模块而言,Y 中的名称数据库变得无关紧要!所以我们会假装它不存在。
要使用这个东西,你(或其他人)会将存储库X克隆到副本X2 然后 select 一些在 X2 内提交以检查。您将在 X2 中使用新名称数据库(它独立于 X 中的名称数据库——您的分支名称不是它们的分支名称—但 是 至少 primed 从那个)选择提交哈希 ID。然后你将在 X2 克隆中 运行 git submodule update --init
,它将读取结帐提取的 .gitmodules
文件,以便它知道去哪里克隆 Y 使 Y2 在 X2.
将 Y 克隆到 Y2 后,Git 操作 in X2 需要知道要检出 Y2 中的哪个提交。这就是 Y2 名称数据库变得无关紧要的地方。您的 Git 软件在您的 X2 中运行,获取 哈希 ID 以在 Y2[=91= 中使用] 来自 commit in X2。哪个提交?为什么,current 提交,提供 .gitmodules
文件的提交以及首先有一个 Y 的事实。
您在 X 或 X2 中所做的每个提交都带有 正确的 提交在 Y 或 Y2 中查看。因此,如果您曾经向 Y 存储库添加新提交,那么您还必须返回相应的 X 超级项目,运行 git add
从更新的 Y 中获取新的哈希 ID,运行 git commit
在 X 在新的 X 提交中记录新的哈希 ID。这样,这个 X 的任何克隆都将知道获得 new Y 提交。 X 的克隆未使用任何 Y names-database 来获取 Y[=91= 的提交哈希 ID ] 子模块。他们使用提交 within 超级项目 X.
换句话说,就是hash ID从哪里来的问题。分支名称输入 branch-and-other-names 数据库中的 Git 克隆,但它们很容易更改。控制子模块的超级项目需要一个严格的、不可更改的标识符,以便提交在子模块中检出——这是一个 哈希 ID,而不是名称。
(人类有时想要比这更大的灵活性,子模块给出的第一个答案是“艰难的 s**t”。但是,Git 现在确实有一些机制来记录分支名称并尝试使用它们。但是向后兼容性意味着这些机制非常笨拙而且非常 user-unfriendly,我不推荐它们,因为它们不仅笨拙,而且很脆弱。知道 原始设计是什么 这就是为什么子模块的行为方式和使用方式。)
好吧,这很尴尬,我们花了太长时间才弄明白,因为我们没有正确阅读,正如你已经从问题中看出的那样。
它在我的机器上运行良好而在我同事的机器上运行良好的原因是因为我使用 https
检查存储库而他使用 SSH
。该子模块包含在 https
url 中,但失败了。我使用了此处建议的相对路径