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

Mau*_*fer 301 git git-submodules

我有一个带有子模块的项目,该子模块指向无效的提交:子模块提交仍然是本地的,当我尝试从另一个repo获取它时,我得到:

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'
Run Code Online (Sandbox Code Playgroud)

我知道子模块HEAD应该是什么,有什么办法,我可以在当地改变这一状况,在不脱离回购推确实已经提交2d7cfbd09fc96c04c4c41148d44ed7778add6b43

我不确定我是否清楚...... 这是我发现的类似情况.

Chr*_*sen 377

假设子模块的存储库确实包含您要使用的提交(与从超级项目的当前状态引用的提交不同),有两种方法可以执行此操作.

第一个要求您已经知道要使用的子模块的提交.它通过直接调整子模块然后更新超级项目从"内部,外部"工作.第二个工作来自"外部,中",通过查找超级项目的修改子模块的提交,然后重置超级项目的索引来引用不同的子模块提交.

反了

如果你已经知道其呈交你想要的子模块使用,cd子模块,检查出你想要的承诺,那么git addgit commit它放回超级项目.

例:

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
Run Code Online (Sandbox Code Playgroud)

哎呀,有人做了一个超级项目提交,它引用了子模块中未发布的提交sub.不知何故,我们已经知道我们希望子模块处于提交状态5d5a3ee314476701a20f2c6ec4a53f88d651df6c.去那里直接看看.

子模块中的结帐

$ 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 ..
Run Code Online (Sandbox Code Playgroud)

由于我们正在检查提交,因此在子模块中生成一个分离的HEAD.如果要确保子模块正在使用分支,则使用git checkout -b newbranch <commit>在提交时创建和签出分支或签出所需的分支(例如,在提示处具有所需提交的分支).

更新超级项目

子模块中的结账在超级项目中反映为对工作树的更改.因此,我们需要在超级项目的索引中进行更改并验证结果.

$ git add sub
Run Code Online (Sandbox Code Playgroud)

检查结果

$ 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
Run Code Online (Sandbox Code Playgroud)

子模块更新是静默的,因为子模块已经在指定的提交中.第一个差异显示索引和工作树是相同的.第三个差异表明,唯一的分阶段变化是将sub子模块移动到另一个提交.

承诺

git commit
Run Code Online (Sandbox Code Playgroud)

这将提交修复后的子模块条目.


外面,在

如果您不确定应该从子模块中使用哪个提交,则可以查看超级项目中的历史记录以指导您.您还可以直接从超级项目管理重置.

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
Run Code Online (Sandbox Code Playgroud)

这与上述情况相同.但这一次我们将重点从超级项目中修复它,而不是浸入子模块中.

找到超级项目的错误提交

$ 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
Run Code Online (Sandbox Code Playgroud)

好吧,它看起来很糟糕ce5d37c,所以我们将从其父(ce5d37c~)恢复子模块.

或者,您可以从补丁文本(5d5a3ee314476701a20f2c6ec4a53f88d651df6c)中获取子模块的提交,并使用上面的"内部,外部"过程.

超级项目结账

$ git checkout ce5d37c~ -- sub
Run Code Online (Sandbox Code Playgroud)

sub会将子模块条目重置为ce5d37c~超级项目中提交的内容.

更新子模块

$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'
Run Code Online (Sandbox Code Playgroud)

子模块更新正常(它表示已分离的HEAD).

检查结果

$ 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
Run Code Online (Sandbox Code Playgroud)

第一个差异显示sub现在是相同的ce5d37c~.第二个差异显示索引和工作树是相同的.第三个差异显示唯一的分阶段变化是将sub子模块移动到另一个提交.

承诺

git commit
Run Code Online (Sandbox Code Playgroud)

这将提交修复后的子模块条目.

  • @Garrett:假设`e47c0a`是`sub`的本地存储库中不存在的提交,但超级项目的`sub`指向该提交.这可能是因为有人在他们的`sub`副本中创建了`e47c0a`,更新了他们的超级项目以指向该提交并推送超级项目而不将`e47c0a`推送到`sub`的中央/共享存储库.当我们从中央/共享超级项目中获取时,我们得到一个将"sub"指向"e47c0a"的提交,但我们无法"看到"该提交.`ce5d37c`是可疑的,因为基于差异,它引入了`e47c0a`. (5认同)

小智 187

试试这个:

git submodule sync
git submodule update
Run Code Online (Sandbox Code Playgroud)

  • 事实证明,在给定子模块的远程URL已更改的情况下,执行`git submodule sync`是必要的.在我们的例子中,我们从公共仓库中添加了我们的子模块,然后将URL更改为私有分支 - 并让我们自己进入这个特定的泡菜. (12认同)
  • 也为我工作过.很想知道为什么. (9认同)
  • 不幸的是,我的子模块之一被主git存储库用add命令作为目标,现在无法撤消它 (2认同)
  • 假设没有人真的搞砸了(在这种情况下你需要克里斯约翰森出色的答案)Lonre Wang的答案应该解决问题,...除非你的子模块有自己的子模块(问题在子模块内).在这种情况下,您需要cd进入具有问题的子模块的子模块并执行上述命令.请注意,update有一个--recursive选项(git submodule update --recursive),但是sync没有; 你真的必须在具有有问题的子(子)模块的子模块内手动运行'git submodule sync'.这是我的问题;). (2认同)

Dan*_*dok 16

此错误可能意味着子模块中缺少提交.也就是说,存储库(A)具有子模块(B).A想要加载B以使其指向某个提交(在B中).如果该提交以某种方式丢失,您将得到该错误.一旦可能的原因:对提交的引用被推入A,但是实际的提交没有从B推出.所以我从那里开始.

不太可能,存在权限问题,并且无法提取提交(如果您使用git + ssh,则可能).

确保子模块路径在.git/config和.gitmodules中看起来正常.

最后一件事 - 在子模块目录中:git reset HEAD --hard

  • "git reset HEAD --hard"也帮助了我......没有别的办法.我也试过以前的解决方案,没有骰子.谢谢! (4认同)
  • 我已经在问题中解释过...问题本身就是如何解决它.它已经在两年前成功回答了...权限与此无关. (3认同)

chr*_*lly 10

可能的原因

这可能发生在:

  1. 子模块已经过编辑
  2. 提交的子模块,它更新被指向的子模块的哈希值
  3. 子模块未被推动.

例如这样的事情发生了:

$ cd submodule
$ emacs my_source_file  # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"
Run Code Online (Sandbox Code Playgroud)

此时应该有子模块.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master
Run Code Online (Sandbox Code Playgroud)

因此,远程用户无法找到丢失的提交,因为它们仍在本地磁盘上.

将修改子模块的人告知,即

$ cd submodule
$ git push
Run Code Online (Sandbox Code Playgroud)


小智 7

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


Pla*_*ato 6

我这样做时遇到了这个错误:

$ git submodule update --init --depth 1
Run Code Online (Sandbox Code Playgroud)

但是父项目中的提交指向了较早的提交。

删除子模块文件夹并运行:

$ git submodule update --init
Run Code Online (Sandbox Code Playgroud)

没有解决问题。我删除了回购协议,然后在没有深度标志的情况下再次尝试,它正常工作。

此错误在Ubuntu 16.04 git 2.7.4中发生,但在Ubuntu 18.04 git 2.17中不发生,TODO查找确切的修复提交或版本。

  • 真烦人 当我不需要回购历史记录时,--depth = 1可以节省很多带宽。如果有人发现或知道为什么会这样,我很想知道。 (3认同)

小智 5

当您有一个子模块指向已重新建立基础的存储库,并且给定的提交为“ gone”时,也会发生这种情况。尽管提交可能仍在远程存储库中,但它不在分支中。如果您不能创建一个新分支(例如,不是您的存储库),那么您就不得不更新超级项目以指向一个新的提交。或者,您可以将子模块的副本之一推送到其他位置,然后更新超级项目以指向该存储库。