【问题标题】:Git can't checkout to commit which have empty directory (error: invalid object 160000; null sha1; fatal: unable to write new index file)Git 无法检出具有空目录的提交(错误:无效对象 160000;null sha1;致命:无法写入新的索引文件)
【发布时间】:2020-08-20 23:53:21
【问题描述】:

我有分支“开发”。最后一个分支 dev 有空文件夹 libtai-mutoso。我在 Windows 上使用 Gitbash。 我已经完成了另一个分支的工作,我正在尝试将 git 切换到分支“dev”。但是git不要结帐:

$ git checkout dev -f
error: invalid object 160000 0000000000000000000000000000000000000000 for 'Src/time/libtai-mutoso'
error: invalid object 160000 0000000000000000000000000000000000000000 for 'Src/time/libtai-mutoso'
error: cache entry has null sha1: Src/time/libtai-mutoso
fatal: unable to write new index file

我现在如何切换到 dev 分支? 谢谢各位高手帮忙!

【问题讨论】:

  • git branch -a 的输出是什么?
  • 检查this out,因为有时“无法写入新的索引文件”是由于磁盘权限,没有磁盘空间,硬盘驱动器断开。只是为了确保这不是你的情况
  • 您正在使用-f 选项,这将强制删除您所做的任何更改,请确保 git 没有文件访问权限问题(是否有任何文件在其他地方打开?)
  • 可敬的蒂姆,可敬的守护进程,原谅我迷路了!
  • 感谢您的帮助。

标签: git checkout


【解决方案1】:

最后一个分支 dev 有空文件夹 libtai-mutoso。

Git 字面上不能 存储一个空文件夹,而你的文件夹没有这样做。发生的事情是有人试图欺骗你的 Git 存储一个空文件夹......但这个伎俩失败了。

有两个相关的技巧,都在How can I add an empty directory to a Git repository? 中描述了一个是使用特殊的空树 哈希,如this answer 中描述的。正如答案本身所指出的那样,它确实无法正常工作。另一种是使用this answer 中描述的空子模块。此方法确实有效(有一些限制)。

看起来,无论谁构建了您已克隆并现在尝试使用的存储库,都尝试使用子模块技巧,但弄错了。

子模块技巧利用了这样一个事实,即当 Git 将有关子模块的信息存储在所谓的 gitlink 中时,即您在错误消息中看到的带有 mode 160000 的实体 - 超级项目Git 将创建一个目录/文件夹,然后——稍后,当你告诉它——在该目录中创建一个 .git 并克隆子模块并使用子模块克隆来填充该目录的内容。

注意这个新目录/文件夹最后不是空的:它包含一个.git,然后你的超级项目Git也运行git checkout,在某个时候,填写包含子模块中某些提交内容的文件夹。但所有这些都会在以后发生,当你告诉你的 Git 去做时。如果你从来不告诉你的 Git填写我的子模块,它甚至永远不会进入创建 .git 的步骤。1

你的 Git 需要的信息,比如你的超级项目 Git 应该克隆的 Git 存储库以及它应该在之后检查的提交,都包含在超级项目的两个位置:

  • 子模块存储库的名称和 URL 位于 .gitmodules,并且
  • 超级项目 Git 在子模块中应该git checkout 的提交哈希 ID 是您在上面的错误消息中看到的哈希 ID。

哈希 ID 必须是该子模块存储库中实际存在的某个提交的有效哈希 ID。超级项目 Git 通常不会检查它是否有效——反正现在还没有:检查会在以后发生。但是有一种特殊情况,你刚刚看到了。

具体来说,Git 中的哈希 ID 0000000000000000000000000000000000000000(40 个零)是保留的,在某些地方称为 null hash IDnull sha1,包括你看到的错误信息:

error: cache entry has null sha1

缓存条目只能在某些特殊情况下具有此空哈希 ID,而这不是其中一种特殊情况。

在您的 Git 对超级项目提交进行git checkout 时需要存在正确的信息,这样您的 Git 就不会抱怨有问题并拒绝检查提交。但是在您克隆的存储库中,您尝试签出的提交中的信息是错误的。

所以,总结一下问题:有人尝试使用子模块技巧,但弄错了。结果是 你的 Git 拒绝签出的提交。

现在如何切换到 dev 分支?

让创建存储库的人停止错误地使用子模块。

您(和他们)最好的选择是根本不用费心尝试存储一个空文件夹。这不值得麻烦。如果他们打算存储一个真正的子模块——这是可能的——让他们修复他们的存储库,以便它有一个正确的子模块。


1如果你告诉你的超级项目 Git 更新子模块,如果你使用了有效的“空子模块”技巧,你克隆的存储库有其提交中没有文件。该答案中的示例使用提交e84d7b81f0033399e325b8037ed2b801a5c994e0。因此,该目录最终包含一个条目,名为.git。在现代 Git 中,.git 是一个包含单行的文件。在较旧的 Git 版本中,它是一个包含空子模块存储库克隆的目录,其中包含一个没有文件的提交。

【讨论】:

  • 感谢您的回答!但是我的项目中没有一个子模块。当开发分支有空文件夹并且分支已经用空文件夹提交时,问题就出现了。签出具有空文件夹的提交会调用错误!
  • 我不明白这个决定,但是当我通过嵌入到 Eclipse 中的 git 进行相同的检出操作时,即使提交中的文件夹为空,分支 dev 也已打开。不幸的是,eclipse下的git不打印使用过的命令。所以,我不明白这个决定。
  • 看起来 Eclipse(它有自己的完整的 Java 内 Git 实现)可能使它成为一个特殊的 Eclipse-only 功能,也许。也许这就是它在 Git 中不起作用的原因。
猜你喜欢
  • 2013-04-10
  • 2011-04-18
  • 1970-01-01
  • 2022-08-08
  • 2014-10-25
  • 2019-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多