子模块已提交的分支不再可用

时间:2018-10-15 09:06:16

标签: git git-submodules

在存储库中,分支将子模块(称为子存储库)设置为特定提交。但是,此提交不再存在(合并到另一个提交中)。现在,当我尝试拉回购分支时,出现此错误:

git submodule update --init sub-repo
fatal: reference is not a tree: xxxxx
Unable to checkout 'xxxxx' in submodule path 'sub-repo'

我能够通过手动拉出子模块然后提交来解决问题

git checkout --branch valid-branch sub-repo
git add sub-repo
git commit

但是我不确定这是否是系统的方法。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

TL; DR:您所做的很好,尽管可能不完整。


这是子模块的一个普遍缺陷:它们通过散列ID 依赖精确的提交散列。超级项目记录子模块提交的哈希ID,作为超级项目提交的一部分。

通常,人们不会从Git存储库中删除提交,因此可行。我们将其称为超级项目存储库 R ,子模块存储库 S (“超级项目”和“子模块”都开始与S,但它们不能同时为S)。 R 中的某些提交告诉Git: S 内,通过此保存的哈希ID检出提交C一旦C S 中不再存在,所有那些 R < / em> 提交现在无效。因此,如果您将回购 S 用作子模块,并且您依赖于 S 中的提交C,则有人会删除{来自 S 的{1}},您会遇到此问题。在一个存储库中,不可能删除其余存储库所需的提交。但是跨单独的存储库,其中的依赖关系只是一个原始哈希ID, S 甚至都不知道 R < / em> 正在使用,这很容易做到,包括误输入。

除了“不要那样做”之外,解决方案还应进入超级项目(存储库 R )中,并进行引用其他一些提交的新提交。在 S 中,或者完全不再使用 S 。如果您同时控制两个存储库,或者有理由相信 S (或 S 中的某些提交)应该稳定并永久存在,请保持 S 作为子模块是合理的。如果您无法控制 S 并且被证明是不稳定的,那么像这样依赖它可能是不明智的。

由于子模块是Git存储库,因此您在其中选择提交的方式是将C放入其中并将其作为Git存储库使用(这就是您所做的) 。然后,一旦子模块在您确定这次稳定的某个新提交cd上,就可以按照您的方式在 R 中进行新提交做到了。如果旧的 R 提交与新的提交唯一不同的是,新的提交具有不同的子模块哈希,则可以在 < em> R 。是旧提交的新改进版。

您可能会考虑丢弃所有引用 S 中的C2的旧提交(和/或替换为新的和改进的版本) ,但 1 ,如果可行的话,因为删除C破坏了它们。做到这一点很难,这就是为什么没有工具的原因(除非the BFG已经开发了子模块替换工具)。可能应该有一个C过滤器专门用于替换子模块。但是,即使找到这些提交也有些棘手:您必须仔细检查并可能将其复制到新改进的替换提交中,即 R < / strong>。这就是两个工具(BFG和git filter-branch)都要做的。 (总的来说,他们希望对某些文件进行更改,而不是对某些子模块进行更改,但这意味着它们拥有所有逻辑和所有内容,只需要一些方法来标识和替换子模块哈希ID。 )


1 如下注释中所述,这是从 R 到(git submodule-in- < em> S ),即不再存在的提交。

答案 1 :(得分:-2)

cd sub-repo
git reset --hard HEAD
git pull origin 'your branch name'
cd ../