Git子模块头'引用不是树'的错误
我有一个子模块项目指向一个无效的提交:子模块提交保持本地,当我试图从另一个回购获取它:
$ git submodule update fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43 Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'
我知道子模块HEAD应该是什么,有没有什么办法可以在本地进行更改,而无需从提交2d7cfbd09fc96c04c4c41148d44ed7778add6b43
的回购中2d7cfbd09fc96c04c4c41148d44ed7778add6b43
?
我不确定我是否清楚…我发现了类似的情况 。
假设子模块的存储库确实包含您想要使用的提交(与从超级项目当前状态引用的提交不同),有两种方法可以实现。
第一个要求您已经知道要使用的子模块提交。 它通过直接调整子模块,然后更新超级项目,从“内部,外部”进行工作。 第二个工作是从“outside,in”开始,通过查找超级项目的提交来修改子模块,然后重新设置超级项目的索引来引用不同的子模块提交。
反了
如果你已经知道你希望子模块使用哪个提交,请cd
到子模块,检查你想要的提交,然后git add
和git commit
它git commit
回超级项目。
例:
$ git submodule update fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556 Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
糟糕的是,有人做了一个超级项目提交,提交了子模块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 ..
由于我们正在检出一个提交,这会在子模块中产生一个分离的HEAD。 如果你想确保子模块正在使用一个分支,那么使用git checkout -b newbranch <commit>
在git checkout -b newbranch <commit>
时创build并签出一个分支,或者检出你想要的分支(例如,在提示中需要提交的分支) )。
更新超级项目
子模块中的签出会在超级项目中反映为对工作树的更改。 因此,我们需要在超级项目的索引中进行变更并validation结果。
$ 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
这提交了固定的子模块条目。
外面,在
如果您不确定从子模块中应该使用哪个提交,则可以查看超级项目中的历史logging来指导您。 您也可以直接从超级项目pipe理重置。
$ git submodule update fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556 Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'
这与上面的情况是一样的。 但是这次我们将把重点放在从超级项目中解决,而不是陷入子模块。
find超级项目的恶意提交
$ 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~
的内容。
更新子模块
$ git submodule update Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'
子模块更新成功(表示分离的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
第一个差异显示,现在sub
在ce5d37c~
是相同的。 第二个差异表明索引和工作树是一样的。 第三个差异显示了唯一的阶段性变化是将sub
子模块移动到另一个提交。
承诺
git commit
这提交了固定的子模块条目。
尝试这个:
git submodule sync git submodule update
这个错误可能意味着子模块中缺less一个提交。 也就是说,存储库(A)有一个子模块(B)。 A想要加载B,以便它指向某个提交(在B中)。 如果这个提交失败了,你会得到这个错误。 一旦可能的原因:对提交的引用被推入A,但实际的提交不是从B推。所以我会开始在那里。
不太可能,有一个权限问题,提交不能被拉(可能,如果你使用git + ssh)。
确保.git / config和.gitmodules中的子模块path正常。
最后一件尝试 – 在子模块目录中:git reset HEAD –hard
可能的原因
这可能发生在:
- 子模块已经被编辑
- 提交的子模块更新所指向的子模块的散列
- 子模块没有按下 。
像这样的事情发生了:
$ 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
我遇到这个错误时:
$ git submodule update --init --depth 1
但是父项目中的提交指向了更早的提交。
删除子模块文件夹并运行
$ git submodule update --init
没有解决问题。 我删除了回购,并没有深度标志再次尝试,它的工作。
当您有一个子模块指向一个已重新绑定的存储库并且给定的提交“已离开”时,也可能发生这种情况。 虽然提交可能仍在远程存储库中,但它不在分支中。 如果你不能创build一个新的分支(例如不是你的仓库),那你就不得不更新超级项目来指向一个新的提交。 或者,您可以将其中一个子模块的其中一个副本推送到其他位置,然后将超级项目更新为指向该存储库。
这个答案是用于SourceTree的用户与有限的terminal混帐经验。
从Git项目(超级项目)中打开有问题的子模块。
获取并确保检查“取所有标签”。
重新拉你的Git项目。
这将解决“参考不是一棵树”的十个问题。 这一次它不会,是最好的答案描述的terminal修复。
无论如何,你的子模块历史logging都保存在submodule git中。
那么,为什么不删除子模块并重新添加呢?
否则,您是否尝试手动编辑子模块.git
的HEAD
或refs/master/head
可以肯定的是,尝试更新你的git
二进制文件。
GitHub for Windows的版本git version 1.8.4.msysgit.0
,在我的情况是这个问题。 更新解决了它。
就我而言,上面的答案都不能解决问题,即使他们是好答案。 所以我发布我的解决scheme(在我的情况下有两个git客户端,客户端A和B):
-
去子模块的目录:
cd sub
-
结账掌握:
git checkout master
-
重新绑定到客户端可以看到的提交代码
-
回到父母的目录:
-
承诺掌握
-
换到另一个客户端,再次
rebase
。 -
终于现在工作正常! 也许失去了几个提交,但它的作品。
-
仅供参考,不要尝试删除你的子模块,它将保持
.git/modules
在那里,不能再读这个子模块,除非被动的本地模块。
要将git repo与子模块的头同步,万一你真的想要,我发现删除子模块然后读取它避免了修改历史。 不幸的是,删除一个子模块需要黑客,而不是一个单一的git命令,但可行。
我通过https://gist.github.com/kyleturner/1563153启发删除子模块的步骤:;
- 运行git rm –cached
- 从.gitmodules文件中删除相关的行。
- 从.git / config中删除相关部分。
- 删除现在未跟踪的子模块文件。
- 删除目录.git / modules /
同样,如果您只需要再次指向子模块的头部,并且您不需要保持子模块的本地副本完好无损,就可以实现这一点。 它假设你有子模块“正确”作为自己的回购,无论它的起源在哪里,你只是想回到正确的包括它作为一个子模块。
注意:除了简单的提交或推送之外,在进行这些types的操作或任何git命令之前,请始终完整地复制项目。 我build议,所有其他的答案,以及作为一个总的git指导方针。