Git子模块头'引用不是树'错误

时间:2010-01-28 16:03:40

标签: git git-submodules

我有一个带有子模块的项目,该子模块指向无效的提交:子模块提交仍然是本地的,当我尝试从另一个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我找到了。

13 个答案:

答案 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)

可能的原因

这可能发生在:

  1. 已对子模块进行了编辑
  2. 提交的子模块,更新指向的子模块的哈希
  3. 子模块未推
  4. 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):

  1. 转到子模块的目录:

    cd sub
    
  2. 结帐主人:

    git checkout master
    
  3. 重新绑定到两个客户端都可以看到的提交代码

  4. 回到父母的主持人:

  5. 承诺掌握

  6. 更改为其他客户,再次rebase

  7. 最后它现在正常运作!可能会失去一些提交,但它确实有效。

  8. 仅供参考,不要尝试删除您的子模块,它将保持.git/modules,并且无法再次读取此子模块,除非是被动的本地模块。

答案 10 :(得分:0)

要将git repo与子模块的头部同步,以防万一你真正想要的东西,我发现删除子模块然后读取它就可以避免修改历史记录。不幸的是,删除子模块需要黑客而不是单个git命令,但可行。

我遵循以下步骤删除子模块,灵感来自https://gist.github.com/kyleturner/1563153

  1. 运行git rm --cached
  2. 从.gitmodules文件中删除相关行。
  3. 从.git / config。
  4. 删除相关部分
  5. 删除现在未跟踪的子模块文件。
  6. 删除目录.git / modules /
  7. 同样,如果您想要的只是再次指向子模块的头部,这可能很有用,并且您不需要保持子模块的本地副本完好无损。它假定你将子模块“正确”作为它自己的repo,无论它的来源是什么,你只想回到正确包含它作为子模块。

    注意:除了简单的提交或推送之外,在进行这些操作或任何git命令之前,请始终制作项目的完整副本。我会建议所有其他答案,以及一般的git指南。

答案 11 :(得分:0)

偶然发现了这个问题,这些解决方案都不适用于我。结果是我的问题的解决方案实际上更简单:升级Git。我的是1.7.1,在我升级到2.16.1(最新版)后,问题消失得无影无踪!猜猜我要把它留在这里,希望它有所帮助。

答案 12 :(得分:0)

您的分支机构可能不是最新的,这是一个简单的解决方案,但是请尝试git fetch