我有一个带有子模块的项目,该子模块指向无效的提交:子模块提交仍然是本地的,当我尝试从另一个repo中获取它时,我得到:
$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'
我知道子模块HEAD应该是什么,有没有什么方法可以在本地更改它,而不是从 提交<{1}}的仓库推送?
我不确定我是否清楚...... here's a similar situation我找到了。
答案 0 :(得分:371)
假设子模块的存储库确实包含您要使用的提交(与从超级项目的当前状态引用的提交不同),有两种方法可以执行此操作。
第一个要求您已经知道要使用的子模块的提交。它通过直接调整子模块然后更新超级项目从“内部,外部”工作。第二个工作来自“outside,in”,通过查找超级项目的修改子模块的提交,然后重新设置超级项目的索引以引用不同的子模块提交。
如果您已经知道子模块要使用哪个提交,cd
到子模块,请检查您想要的提交,然后{ - 1}}和git add
将其返回到超级模块项目
示例:
git commit
哎呀,有人做了一个超级项目提交,它引用了子模块$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
中未发布的提交。不知何故,我们已经知道我们希望子模块处于提交sub
。去那里直接看看。
5d5a3ee314476701a20f2c6ec4a53f88d651df6c
由于我们正在检查提交,因此会在子模块中生成一个分离的HEAD。如果要确保子模块正在使用分支,则使用$ cd sub
$ git checkout 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
Note: moving to '5d5a3ee314476701a20f2c6ec4a53f88d651df6c' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
git checkout -b <new_branch_name>
HEAD is now at 5d5a3ee... quux
$ cd ..
在提交时创建并签出分支,或者检出所需的分支(例如,在提示处具有所需提交的分支)。 / p>
子模块中的结账在超级项目中反映为对工作树的更改。因此,我们需要在超级项目的索引中进行更改并验证结果。
git checkout -b newbranch <commit>
$ git add sub
子模块更新是静默的,因为子模块已经在指定的提交中。第一个差异显示索引和工作树是相同的。第三个差异表明,唯一的分阶段变化是将$ git submodule update
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
子模块移动到另一个提交。
sub
这将提交修复后的子模块条目。
如果您不确定应该从子模块中使用哪个提交,您可以查看超级项目中的历史记录以指导您。您也可以直接从超级项目管理重置。
git commit
这与上述情况相同。但这次我们将重点从超级项目中修复它,而不是潜入子模块。
$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
好吧,看起来它在$ git log --oneline -p -- sub
ce5d37c local change in sub
diff --git a/sub b/sub
index 5d5a3ee..e47c0a1 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
+Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
bca4663 added sub
diff --git a/sub b/sub
new file mode 160000
index 0000000..5d5a3ee
--- /dev/null
+++ b/sub
@@ -0,0 +1 @@
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
中变坏了,所以我们将从其父级(ce5d37c
)恢复子模块。
或者,您可以从补丁文本(ce5d37c~
)中获取子模块的提交,并使用上面的“内部,外部”过程。
5d5a3ee314476701a20f2c6ec4a53f88d651df6c
这会将$ git checkout ce5d37c~ -- sub
的子模块条目重置为超级项目中提交sub
的条目。
ce5d37c~
子模块更新正常(它表示已分离的HEAD)。
$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'
第一个差异显示$ git diff ce5d37c~ -- sub
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
现在sub
中的ce5d37c~
相同。第二个差异显示索引和工作树是相同的。第三个差异显示唯一的分阶段更改是将sub
子模块移动到另一个提交。
git commit
这将提交修复后的子模块条目。
答案 1 :(得分:184)
试试这个:
git submodule sync
git submodule update
答案 2 :(得分:15)
此错误可能意味着子模块中缺少提交。也就是说,存储库(A)具有子模块(B)。 A想要加载B以使其指向某个提交(在B中)。如果该提交以某种方式丢失,您将得到该错误。一旦可能的原因:对提交的引用被推送到A中,但是实际的提交没有从B推出。所以我从那里开始。
不太可能存在权限问题,并且无法提取提交(如果您使用的是git + ssh,则可能)。
确保.git / config和.gitmodules中的子模块路径看起来不错。
最后一件事 - 在子模块目录中:git reset HEAD --hard
答案 3 :(得分:9)
这可能发生在:
e.g。这样的事情发生了:
$ cd submodule
$ emacs my_source_file # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"
此时应该推送子模块。
$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master
因此,远程用户无法找到丢失的提交,因为它们仍在本地磁盘上。
通知修改子模块的人,即
$ cd submodule
$ git push
答案 4 :(得分:5)
我做错了这个错误:
$ git submodule update --init --depth 1
但是父项目中的提交指向了先前的提交。
删除子模块文件夹并运行:
$ git submodule update --init
没有解决问题。我删除了回购并再次尝试没有深度标记,并且它有效。
在Ubuntu 16.04 git 2.7.4中发生此错误,但在Ubuntu 18.04 git 2.17上没有,TODO发现确切的修复提交或版本。
答案 5 :(得分:4)
如果您的子模块指向已重新定位的存储库并且给定的提交已“消失”,则也可能发生这种情况。虽然提交可能仍在远程存储库中,但它不在分支中。如果您无法创建新分支(例如,不是您的存储库),那么您必须更新超级项目以指向新的提交。或者,您可以将其中一个子模块的副本推送到其他位置,然后将超级项目更新为指向该存储库。
答案 6 :(得分:1)
这个答案适用于具有有限终端git体验的SourceTree用户。
从Git项目(超级项目)中打开有问题的子模块。
获取并确保“获取所有标记”#39;检查。
Rebase拉你的Git项目。
这将解决&#39;引用不是树&#39;十分之九的问题。它赢了一次,是最终答案所描述的终端修复。
答案 7 :(得分:0)
您的子模块历史记录无论如何都安全地保存在子模块git中。
那么,为什么不删除子模块并重新添加呢?
否则,您是否尝试手动修改子模块HEAD
中的refs/master/head
或.git
答案 8 :(得分:0)
确定,请尝试更新git
二进制文件。
GitHub for Windows的版本为git version 1.8.4.msysgit.0
,在我的情况下是问题所在。更新解决了它。
答案 9 :(得分:0)
在我的情况下,上面的答案都没有解决问题,即使他们是好的答案。所以我发布我的解决方案(在我的情况下有两个git客户端,客户端A和B):
转到子模块的目录:
cd sub
结帐主人:
git checkout master
重新绑定到两个客户端都可以看到的提交代码
回到父母的主持人:
承诺掌握
更改为其他客户,再次rebase
。
最后它现在正常运作!可能会失去一些提交,但它确实有效。
仅供参考,不要尝试删除您的子模块,它将保持.git/modules
,并且无法再次读取此子模块,除非是被动的本地模块。
答案 10 :(得分:0)
要将git repo与子模块的头部同步,以防万一你真正想要的东西,我发现删除子模块然后读取它就可以避免修改历史记录。不幸的是,删除子模块需要黑客而不是单个git命令,但可行。
我遵循以下步骤删除子模块,灵感来自https://gist.github.com/kyleturner/1563153:
同样,如果您想要的只是再次指向子模块的头部,这可能很有用,并且您不需要保持子模块的本地副本完好无损。它假定你将子模块“正确”作为它自己的repo,无论它的来源是什么,你只想回到正确包含它作为子模块。
注意:除了简单的提交或推送之外,在进行这些操作或任何git命令之前,请始终制作项目的完整副本。我会建议所有其他答案,以及一般的git指南。
答案 11 :(得分:0)
偶然发现了这个问题,这些解决方案都不适用于我。结果是我的问题的解决方案实际上更简单:升级Git。我的是1.7.1,在我升级到2.16.1(最新版)后,问题消失得无影无踪!猜猜我要把它留在这里,希望它有所帮助。
答案 12 :(得分:0)
您的分支机构可能不是最新的,这是一个简单的解决方案,但是请尝试git fetch