Git提示“fatal: confused by unstable object source data”。

29
为了好玩,我试图将大约85GB的大小主要在6MB左右的二进制文件放入Git中。Git开始运行一段时间,但总是在一半左右失败,并显示消息“fatal: confused by unstable object source data”,后面跟着一个SHA1。您知道原因吗?有什么方法可以修复它吗?
7个回答

32

要么:

  • 在您的操作期间,一个或多个文件正在被修改,或者
  • 有些东西导致了不一致的读取(例如,硬件故障)。

简短版:Git 的开发人员没有打算将其用于易变文件。

由于 Git 用于“松散对象”的布局*和它所假定的有限文件系统语义**,Git 必须在开始存储新对象之前知道新对象名称(SHA-1)的第一个字节(两个十六进制字符)。

* objects/[0-9a-f][0-9a-f]/ 目录。请参见 gitrepository-layout
** 具体来说,它需要能够执行“原子”文件重命名。某些文件系统(通常是网络文件系统;我认为特别是 AFS)仅在重命名的源和目标位于同一目录内时才保证重命名的原子性。

当前,Git 对每个文件进行两次 SHA-1 操作。第一次操作用于检查 Git 是否已经知道文件的内容(即其 SHA-1 对象名称是否已存在于对象存储中)。如果对象已经存在,则不进行第二次操作。

对于新的内容(对象尚未存在于对象存储中),在压缩和计算正在压缩的数据的 SHA-1 时,文件会再次被读取。压缩后的数据将被写入临时文件,只有当最初的 SHA-1(“已存储?”检查)与稍后的 SHA-1(已压缩并写入的数据的哈希值)匹配时,该文件才会被重命名为其最终松散对象名称。如果这些 SHA-1 哈希值不匹配,则 Git 显示您所看到的错误消息并中止。此错误检查是在 748af44c63 中添加的,该版本首次发布于 Git 1.7.0.2。

我很确定它不是易失性的,但是阅读更多关于git内部的知识仍然非常有教益。我想现在我必须去确保我的磁盘没有出现故障。 - jbfink
17
如果git提示“致命错误:无法处理不稳定的对象源数据”,并跟随一个SHA1,然后再跟着文件名,那就太好了。很烦人它没有告诉你哪个文件是不稳定的...如果它这样做了,我可能会合理地将文件或目录添加到我的.gitignore中。 - Bob Herrmann
7
那么,对于这个问题的解决方案是什么? - Sathish Kumar k k

16

还有一种可能性,即使很小概率。那就是一个非常大的文件(例如3个或更多GB),简单来说,git无法处理它。 我们在尝试在一个包含巨大文件的结构中创建存储库时发现了这个错误。


刚刚遇到一个意外情况,一些几十GB大小的日志文件悄悄地进入了一个Git工作树中。 - fche
大型(但稳定)文件肯定会导致此错误。错误消息具有误导性,并且Git没有事先告诉您文件大小是一个缺点,至少目前是这样的。我尝试过git-annex,这是一种处理大型文件的有前途的方法,但到目前为止,我无法在OS / X上使其正常工作。 - Eric apRhys

4
源代码中,blob的sha1值被计算了两次:
  • write_sha1_file_prepare
  • write_loose_object
这两个函数都是从write_sha1_file调用的(虽然git尝试着让文件系统确认文件未修改,但如果执行touch或类似操作将会失去跟踪)。第一个哈希用于检查对象是否已知;第二个哈希是实际提供给zlib进行压缩和写入的数据的哈希。
由于zlib的存在,第二个哈希可能计算成本更高,这也可以解释为什么要计算两个哈希值(虽然这似乎是历史偶然事件,我猜添加新对象时的性能成本比检测虚假更改时的CPU优势更大)。有人可以添加一种回退方式,以便使用新的sha1重新执行write_changed_sha1存在性检查逻辑,以便添加那些不稳定的文件。这对备份很有用,当添加的文件中有一些文件处于打开状态时。

3

两种可能:

  • 有些东西正在你试图将它们放到git中的文件中写入。

  • 你可能有某种磁盘/内存故障导致数据损坏。


2

虽然其他回答已经非常好地解释了为什么会出现这个错误,但是这里提供一种可能的解决方案:

找到有问题的文件,将 -v 添加到你的 git add 命令中,这将给你一些关于有问题的文件的线索:

git add -Av

问题可能是文件太大了(一个压缩的源文件,一些SQL数据文件):将其添加到.gitignore中。实际上,一个好的做法是定期配置您的.gitignore文件,以避免编译和压缩文件,例如:https://gist.github.com/octocat/9257657

0
根据我的经验,仅仅是添加了大量的文件可能会导致这个错误信息。分几步提交相同的文件并不是个问题。

0

如果您尝试在btrfs文件系统上使用git svn clone或git svn fetch克隆/获取存储库,可能会发生此情况,这可能与btrfs cow功能内部的竞争条件或原子性有关。

例如:

git svn --authors-file=authors.map clone http://svn.example.com/svn/repo repo

或者

cd repo; git svn --authors-file=../authors.map fetch

我发现了一个解决方法,通过设置您的基本工作目录而不进行写时复制:

chattr +C .

然后你需要复制所有的数据(例如):

cp -fr repo repo.new; rm -fr repo; mv -f repo.new repo

cp authors.map authors.map.new; mv -f authors.map.new authors.map

那么它就不应该失败(并且运行得更快)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接