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

发布于 2024-08-19 07:55:26 字数 514 浏览 8 评论 0原文

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

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

我知道子模块 HEAD 应该是什么,有什么方法可以更改它在本地,无需从已提交 2d7cfbd09fc96c04c4c41148d44ed7778add6b43 的存储库推送?

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

I have a project with a submodule that is pointing to an invalid commit: the submodule commit remained local and when I try to fetch it from another repo I get:

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

I know what the submodule HEAD should be, is there any way I can change this locally, without pushing from the repo that does have commit 2d7cfbd09fc96c04c4c41148d44ed7778add6b43 ?

I'm not sure if I'm being clear... here's a similar situation I found.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

臻嫒无言 2024-08-26 07:55:27

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

Your branch may not be up to date, a simple solution but try git fetch

忆梦 2024-08-26 07:55:27

可能的原因

在以下情况下可能会发生这种情况:

  1. 子模块已就地编辑
  2. 子模块已提交,更新了所指向的子模块的哈希值
  3. 子模块未推送。

例如发生了这样的事情:

$ 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

Possible cause

This can happens when:

  1. Submodule(s) have been edited in place
  2. Submodule(s) committed, which updates the hash of the submodule being pointed to
  3. Submodule(s) not pushed.

e.g. something like this happened:

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

Should have submodule pushed at this point.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master

As a result, the missing commits could not possibly be found by the remote user because they are still on the local disk.

Solution

Informa the person who modified the submodule to push, i.e.

$ cd submodule
$ git push
少钕鈤記 2024-08-26 07:55:27

当我这样做时,我得到了这个错误:

$ git submodule update --init --depth 1

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

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

$ git submodule update --init

没有解决问题。我删除了该存储库并在没有深度标志的情况下再次尝试,它起作用了。

此错误发生在 Ubuntu 16.04 git 2.7.4 中,但不会发生在 Ubuntu 18.04 git 2.17 上。

@pavan kumar 在评论中指出:

我刚刚增加了深度计数以包含旧的提交,并且它起作用了。

I got this error when I did:

$ git submodule update --init --depth 1

but the commit in the parent project was pointing at an earlier commit.

Deleting the submodule folder and running:

$ git submodule update --init

did NOT solve the problem. I deleted the repo and tried again without the depth flag and it worked.

This error happens in Ubuntu 16.04 git 2.7.4, but not on Ubuntu 18.04 git 2.17.

@pavan kumar notes in comment:

I just increased the depth count to include the old commit and it worked.

临走之时 2024-08-26 07:55:27

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

This may also happen when you have a submodule pointing to a repository that was rebased and the given commit is "gone". While the commit may still be in the remote repository, it is not in a branch. If you can't create a new branch (e.g. not your repository), you're stuck with having to update the super project to point to a new commit. Alternatively you can push one of your copies of the submodules elsewhere and then update the super-project to point to that repository instead.

木森分化 2024-08-26 07:55:27

这个答案适用于终端 git 经验有限的 SourceTree 用户。

从 Git 项目(超级项目)中打开有问题的子模块。

获取并确保选中“获取所有标签”。

Rebase 拉取您的 Git 项目。

这将解决十分之九的“引用不是树”问题。这一次不会,是一个终端修复,如最上面的答案所述。

This answer is for users of SourceTree with limited terminal git experience.

Open the problematic submodule from within the Git project (super-project).

Fetch and ensure 'Fetch all tags' is checked.

Rebase pull your Git project.

This will solve the 'reference is not a tree' problem 9 out of ten times. That 1 time it won't, is a terminal fix as described by the top answer.

幼儿园老大 2024-08-26 07:55:27

无论如何,你的子模块历史记录都会安全地保存在子模块 git 中。

那么,为什么不直接删除子模块并重新添加呢?

否则,您是否尝试手动编辑子模块 .git 中的 HEADrefs/master/head

Your submodule history is safely preserved in the submodule git anyway.

So, why not just delete the submodule and add it again?

Otherwise, did you try manually editing the HEAD or the refs/master/head within the submodule .git

坦然微笑 2024-08-26 07:55:27

为了确保万无一失,请尝试更新您的 git 二进制文件。

Windows 版 GitHub 的版本是 git version 1.8.4.msysgit.0 ,在我的例子中就是问题所在。更新解决了。

Just to be sure, try updating your git binaries.

GitHub for Windows has the version git version 1.8.4.msysgit.0 which in my case was the problem. Updating solved it.

柒夜笙歌凉 2024-08-26 07:55:27

就我而言,上述答案都不能解决问题,即使它们是很好的答案。所以我发布了我的解决方案(在我的例子中,有两个 git 客户端,客户端 A 和 B):

  1. 转到子模块的目录:

    <前><代码>cd sub

  2. 签出到主模块:

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

  4. 返回到父目录:< /p>

  5. commit to master

  6. 更改为另一个客户端,再次执行rebase

  7. 现在终于可以正常使用了!也许会丢失一些提交,但它可以工作。

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

In my case, none of answer above solve the problem even thoungh they are good answers. So I post my solution (in my case there are two git clients, client A and B):

  1. go to submodule's dir:

    cd sub
    
  2. checkout to master:

    git checkout master
    
  3. rebase to a commit code which both client can see

  4. go back to the parent's dir:

  5. commit to master

  6. change to the other client, do rebase again.

  7. finally it works fine now! Maybe lose a couple of commits but it works.

  8. FYI, don't try to remove your submodule, it will remain .git/modules there and cannot readd this submodule again, unless reactive local one.

溺深海 2024-08-26 07:55:27

为了将 git 存储库与子模块的头部同步,如果这确实是您想要的,我发现删除子模块然后读取它可以避免修改历史记录。不幸的是,删除子模块需要黑客攻击,而不是单个 git 命令,但这是可行的。

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

  1. 运行 git rm --cached
  2. 从 .gitmodules 文件中删除相关行。
  3. 从 .git/config 中删除相关部分。
  4. 删除现在未跟踪的子模块文件。
  5. 删除目录 .git/modules/

同样,如果您只想再次指向子模块的头部,并且您没有因为需要保持子模块的本地副本完整而使事情变得复杂,那么这可能很有用。它假设您将子模块“正确”作为其自己的存储库,无论它的起源在哪里,并且您只想将其正确地包含为子模块。

注意:在进行这些类型的操作或除简单提交或推送之外的任何 git 命令之前,请务必先制作项目的完整副本。我也建议所有其他答案都这样做,并作为一般的 git 指南。

To sync the git repo with the submodule's head, in case that is really what you want, I found that removing the submodule and then readding it avoids the tinkering with the history. Unfortunately removing a submodule requires hacking rather than being a single git command, but doable.

Steps I followed to remove the submodule, inspired by https://gist.github.com/kyleturner/1563153:

  1. Run git rm --cached
  2. Delete the relevant lines from the .gitmodules file.
  3. Delete the relevant section from .git/config.
  4. Delete the now untracked submodule files.
  5. Remove directory .git/modules/

Again, this can be useful if all you want is to point at the submodule's head again, and you haven't complicated things by needing to keep the local copy of the submodule intact. It assumes you have the submodule "right" as its own repo, wherever the origin of it is, and you just want to get back to properly including it as a submodule.

Note: always make a full copy of your project before engaging in these kinds of manipulation or any git command beyond simple commit or push. I'd advise that with all other answers as well, and as a general git guideline.

鹤仙姿 2024-08-26 07:55:27

刚刚偶然发现了这个问题,这些解决方案都不适合我。我的问题的解决方案实际上要简单得多:升级 Git。我的是1.7.1,升级到2.16.1(最新)后,问题就消失得无影无踪了!我想我会把它留在这里,希望它对某人有帮助。

Just stumbled upon this problem, and none of these solutions worked for me. What turned out to be the solution for my issue is actually much simpler: upgrade Git. Mine was 1.7.1, and after I upgraded it to 2.16.1 (latest), the problem went away without a trace! Guess I'm leaving it here, hope it helps someone.

呆橘 2024-08-26 07:55:27

对于那些在 CI 方面看到这一点的人:可能您引用了非合并 PR 中的提交,然后将其与 squash 合并

For those who see this on CI side: probably you reference a commit in the non-merged PR and then merge it with squash

一页 2024-08-26 07:55:26

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

第一个要求您已经知道要使用的子模块的提交。它是“从内到外”工作的,直接调整子模块,然后更新超级项目。第二个方法是从“外、内”开始工作,找到修改子模块的超级项目提交,然后重置超级项目的索引以引用不同的子模块提交。

Inside, Out

如果您已经知道想要子模块使用哪个提交,请cd到子模块,检查您想要的提交,然后git addgit 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在提交时创建并签出分支或签出您想要的分支(例如尖端处带有所需的提交)。

更新超级项目

子模块中的签出会作为对工作树的更改反映在超级项目中。所以我们需要对超级项目的索引进行暂存更改并验证结果。

$ 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'

这和上面的情况是一样的。但这次我们将专注于从超级项目中修复它,而不是将其浸入子模块中。

找到超级项目的 Errant Commit

$ 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

这将提交固定的子模块条目。

Assuming the submodule's repository does contain a commit you want to use (unlike the commit that is referenced from the current state of the super-project), there are two ways to do it.

The first requires you to already know the commit from the submodule that you want to use. It works from the “inside, out” by directly adjusting the submodule then updating the super-project. The second works from the “outside, in” by finding the super-projects commit that modified the submodule and then resetting the super-project's index to refer to a different submodule commit.

Inside, Out

If you already know which commit you to want the submodule to use, cd to the submodule, check out the commit you want, then git add and git commit it back in the super-project.

Example:

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

Oops, someone made a super-project commit that refers to an unpublished commit in the submodule sub. Somehow, we already know that we want the submodule to be at commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c. Go there and check it out directly.

Checkout in the Submodule

$ 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 ..

Since we are checking out a commit, this produces a detached HEAD in the submodule. If you want to make sure that the submodule is using a branch, then use git checkout -b newbranch <commit> to create and checkout a branch at the commit or checkout the branch that you want (e.g. one with the desired commit at the tip).

Update the Super-project

Checkout in the submodule is reflected in the super-project as a change to the working tree. So we need to stage the change in the super-project's index and verify the results.

$ git add sub

Check the Results

$ 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

The submodule update was silent because the submodule is already at the specified commit. The first diff shows that the index and work tree are the same. The third diff shows that the only staged change is moving the sub submodule to a different commit.

Commit

git commit

This commits the fixed-up submodule entry.


Outside, In

If you are not sure which commit you should use from the submodule, you can look at the history in the superproject to guide you. You can also manage the reset directly from the super-project.

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

This is the same situation as above. But this time we will focus on fixing it from the super-project instead of dipping it into the submodule.

Find the Super-project's Errant Commit

$ 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

OK, it looks like it went bad in ce5d37c, so we will restore the submodule from its parent (ce5d37c~).

Alternatively, you can take the submodule's commit from the patch text (5d5a3ee314476701a20f2c6ec4a53f88d651df6c) and use the above “inside, out” process instead.

Checkout in the Super-project

$ git checkout ce5d37c~ -- sub

This resets the submodule entry for sub to what it was at commit ce5d37c~ in the super-project.

Update the Submodule

$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'

The submodule update went OK (it indicates a detached HEAD).

Check the Results

$ 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

The first diff shows that sub is now the same in ce5d37c~. The second diff shows that the index and work tree are the same. The third diff shows the only staged change is moving the sub submodule to a different commit.

Commit

git commit

This commits the fixed-up submodule entry.

勿忘初心 2024-08-26 07:55:26

试试这个:

git submodule sync
git submodule update

try this:

git submodule sync
git submodule update
梦在深巷 2024-08-26 07:55:26

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

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

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

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

This error can mean that a commit is missing in the submodule. That is, the repository (A) has a submodule (B). A wants to load B so that it is pointing to a certain commit (in B). If that commit is somehow missing, you'll get that error. Once possible cause: the reference to the commit was pushed in A, but the actual commit was not pushed from B. So I'd start there.

Less likely, there's a permissions problem, and the commit cannot be pulled (possible if you're using git+ssh).

Make sure the submodule paths look ok in .git/config and .gitmodules.

One last thing to try - inside the submodule directory: git reset HEAD --hard

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文