【问题标题】:git - fatal: your current branch appears to be broken (possibly from interrupted pull)git - 致命:您当前的分支似乎已损坏(可能来自中断的拉动)
【发布时间】:2019-11-02 04:44:16
【问题描述】:

问题:

  1. 不小心执行了 git --amend 并将其从第一台计算机推送到 USB 密钥
  2. 从 USB 密钥拉到第二台计算机
  3. 第二台计算机存储库现已损坏
  4. git pull 到第一台计算机导致合并冲突;对这是否也是损坏状态感到困惑(如果 --amend 已损坏)

症状:

大多数命令:

fatal: your current branch appears to be broken

.git/refs/heads/master:

$ cat .git/refs/heads/master

.git/refs/heads/master 的文件内容:

'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

$ git status
new file: ...
new file: ... [for every file in the repository; expected since on a corrupted branch]

我不确定我是否愿意责怪 git --amend ,因为它看起来有点温和;也许发生了其他事情。

如何解决?:

解决这个问题就像从 .git/logs/refs/heads/master 的最新良好提交中获取哈希并将其手动插入 .git/refs/heads/master 一样简单吗?如果

如果是这样,我是否应该销毁有问题的提交(这样它以后就不会破坏东西,比如git-repack 或其他东西)?

当我尝试less .git/logs/refs/heads/master 并从表单的最后一行获取 [edit:typo] first 哈希时...

...
[hash for HEAD~2] [hash for HEAD~1] [authorname] ...
[hash for HEAD~1] [hash for HEAD] [authorname] ...
^^^^^^^^^^^^^^^^^   (corrupted)
EOF

...然后粘贴到 .git/refs/heads/master 文件中,我现在卡住了...

$ git fsck
error: inflate: data stream error (unknown compression method)
error: unable to unpack header of .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
error: 8f1da374ffac3711f8cdde57379f90cb03bbb9ea: object corrupt or missing: .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
error: inflate: data stream error (unknown compression method)
error: unable to unpack header of .git/objects/ac/2fcd052804fb7adac465220da5bcb04d008fc7
error: ac2fcd052804fb7adac465220da5bcb04d008fc7: object corrupt or missing: .git/objects/ac/2fcd052804fb7adac465220da5bcb04d008fc7
Checking object directories: 100% (256/256), done.
Checking objects: 100% (1147/1147), done.
error: inflate: data stream error (unknown compression method)
error: unable to unpack 8f1da374ffac3711f8cdde57379f90cb03bbb9ea header
error: inflate: data stream error (unknown compression method)
error: unable to unpack 8f1da374ffac3711f8cdde57379f90cb03bbb9ea header
fatal: loose object 8f1da374ffac3711f8cdde57379f90cb03bbb9ea (stored in .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea) is corrupt

我可以尝试销毁松散的对象,但我不确定它是否反过来是指向必须销毁的更多损坏对象的指针(例如树)。如果我知道推荐,我当然可以尝试销毁这个对象(或者可以尝试在备份中rm它);我应该试试吗?

此外,我将如何从这个混乱中修复 USB 密钥和其他 repo?谢谢。

(对新手可能有用的参考资料,不太可能帮助有能力回答这个问题的人:https://aboullaite.me/deep-dive-into-git-git-refs/) (类似问题fatal: your current branch appears to be broken -- 没有说明错误原因;很多事情都可能导致这个错误)


编辑:

我为上面列出的每个对象都做了rm .git/objects/...,现在我...

$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (1147/1147), done.
error: refs/remotes/origin/HEAD: invalid sha1 pointer 0000000000000000000000000000000000000000
error: refs/remotes/origin/master: invalid sha1 pointer 0000000000000000000000000000000000000000
error: HEAD: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
error: refs/heads/master: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
error: bad ref for .git/logs/refs/remotes/origin/HEAD
error: bad ref for .git/logs/refs/remotes/origin/master
error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
broken link from    tree b0d598ef5427d59ed31eb1b315c761fc89af40b7
              to    tree ac2fcd052804fb7adac465220da5bcb04d008fc7
dangling blob f4e39c36cc8df3f9f324c0ccca4ed6a7a3ffe6ac
dangling tree 068716abcf815b4eaf8f0fe74c3020bf6251bba0
dangling blob fb4cfe7c94e8b4d800fdb4935806577b2b99fd94
dangling blob 35cf2ca2ed03811c14f1598c50daacfab9032b8f
missing tree ac2fcd052804fb7adac465220da5bcb04d008fc7
dangling blob d056e38af637cf0de76dac5689a8c5e735d75793
dangling blob 3b3903cc7b4eb035e9c4508024acc3f81c015741
dangling blob b09c3cc95935a327ecf7fad8374f14c4e320f67e

【问题讨论】:

    标签: git corruption git-amend reflog


    【解决方案1】:

    问题的根源很可能是您在操作系统将 USB 密钥写入之前或期间移除了 USB 密钥。这留下了许多损坏的文件。

    由于任何原因不当关闭计算机而损坏的文件(拔出 USB 密钥就是其中之一,但操作系统崩溃、电源故障、计算机着火等等也是如此)往往会导致 最近写的个文件。刚刚安静放置的文件往往完好无损。这里有很多警告,但这个一般原则适用于此。

    • 如果您正在更新分支,则包含分支信息的文件可能会损坏。

      这里,损坏的文件包括.git/refs/heads/master。该文件应包含 41 个字节,其中包含一个 40 字节文本表示的提交的哈希 ID,应被视为分支 master 的尖端,后跟一个 ASCII 换行符。 没有明确的方法来猜测哪个提交是正确的提示提交,这就是为什么 Git 存储问题的答案“什么是提示提交的哈希 ID master* 在某些文件中。

      (在某些种情况下,.git/packed-refs 中可能会提供有效答案,但一般来说,如果.git/refs/heads/master 存在,它应该保留正确答案。正确答案会随着时间而变化,通过你创建新的提交,通过你运行git reset,通过你运行git branch -f,等等。)

    • 损坏的文件很可能包括.git/index,它包含Git 的index暂存区。这两个术语在 Git 中的含义相同,还有第三个现在很少使用的术语,缓存,用于同一个文件。除非您使用索引处理有冲突的合并,否则 in 索引文件中的内容大部分很容易通过一些努力重新计算:Git 使用它来使事情变得更快,即作为缓存,因此是第三个很少使用的术语。

      如果(大多数情况下)缓存包含无法重新计算的任何内容,您可以简单地删除 .git/index,然后运行git reset 重新计算它。这将使所有“新文件...”消息消失,唯一丢失的是您是否进行了某些特定更新。

      mostly 这个词经常出现在这里,因为索引包含您打算放入 next 提交中的所有 blob 对象(“文件”)的哈希 ID .如果您做了一些不寻常的事情,例如创建一个新的唯一版本的文件并将其放入索引中,然后将其从其他任何地方删除,则该文件的唯一版本的哈希 ID 可能在任何地方都不容易找到。当使用git add -pgit reset -p 来暂存与提交版本工作树版本不同的文件的第三个变体时,您可能会得到这个。在这种情况下,删除并重新创建索引(使用rm .git/index; git reset)将使重建该文件的最简单方法是重新运行git add -pgit reset -p 操作。

      在您的情况下,索引似乎有可能被完全删除,导致 Git 声称每个文件都是新的。如果你运行rm .git/index,你会得到同样的结果,所以你最好运行git reset。但是,由于这条消息,这里肯定还有其他事情发生:

      error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
      

      这里的cache-tree 指的是索引中的东西,使用它的旧名称​​cache。但由于这是“缓存”,删除并重新创建索引可以解决问题,具体取决于其他情况。

    • 损坏的文件可能包括您的一些工作树文件。 Git 无法帮助您解决这些问题:管理这些文件的是您计算机的其余部分。当您git checkout 一些现有的提交时,Git 将文件的副本写入 到您的工作树中,以便它们采用您可以查看和使用的形式,但之后,它就是您的全部/您的计算机要管理。

    • 损坏的文件可能包含一些 Git 的内部对象。就您而言,这显然确实发生了:

      error: unable to unpack header of .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
      error: 8f1da374ffac3711f8cdde57379f90cb03bbb9ea: object corrupt or missing: .git/objects/8f/1da374ffac3711f8cdde57379f90cb03bbb9ea
      

      这意味着对象8f1da374ffac3711f8cdde57379f90cb03bbb9ea 已损坏。如果没有进一步的信息,就不可能知道这个对象是什么type,更不用说其中有什么数据以及它们是否有价值。

    • 损坏的文件可能包括各种引用日志,存储在.git/logs/。在这种情况下,您得到:

      invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
      

      和:

      error: refs/heads/master: invalid reflog entry 8f1da374ffac3711f8cdde57379f90cb03bbb9ea
      

      使用相同的号码。这就是我们刚才看到的损坏对象哈希 ID。由于分支名称是必需指向提交对象,我们现在可以猜测8f1da374ffac3711f8cdde57379f90cb03bbb9ea是一个提交对象,在它被损坏之前。它可能是最近创建的提交,例如 git commit --amend 所做的提交。

    从所有这些中,我们可以得出结论——但这仍然是一个猜测——git commit --amend 提交本身被破坏了,master 中损坏的哈希 ID 应该是文本 8f1da374ffac3711f8cdde57379f90cb03bbb9ea。该索引可能已损坏或完全删除,但通常只需将其删除并重建其缓存方面就足够安全了,因此您可以再次删除它(如有必要),然后在您拥有合理的“当前提交”后从当前提交重建它”。您的某些 reflog 可能已损坏,但无论如何 reflog 都是辅助数据:其中没有任何内容对 Git 自身的操作至关重要,因此可以截断损坏的数据。最大的问题是损坏的.git/objects/ 文件。

    如果您愿意丢失该提交,可能只需删除损坏的对象并将有效的哈希 ID 放入 .git/refs/heads/master 即可。当你这样做时,你的 fsck 仍然抱怨:

    error: ac2fcd052804fb7adac465220da5bcb04d008fc7: invalid sha1 pointer in cache-tree
    broken link from    tree b0d598ef5427d59ed31eb1b315c761fc89af40b7
                  to    tree ac2fcd052804fb7adac465220da5bcb04d008fc7
    

    现在,第一行仍然是指从.git/index 读取的内容。 remove-and-reset 将通过将其哈希 ID 写入.git/refs/heads/master 来从您选择的提交中重建索引/缓存。 如果树对象 ac2fcd052804fb7adac465220da5bcb04d008fc7 未在存储库中的其他任何地方使用,则可能会留下完整的存储库。

    如果它,那么只有两种方法可以使这个特定的 Git 存储库自洽:

    1. 删除直接或间接引用该树对象的 所有 提交及其所有后代(如果有)。

    2. 获取或重建丢失的对象。如果它在其他 Git 存储库中——这个存储库的一些克隆——这是获取它的简单方法。在包含它的存储库中运行git cat-file -p ac2fcd052804fb7adac465220da5bcb04d008fc7。结果是树的文本表示。使用git hash-object -t tree -w 在 USB 密钥存储库中创建对象,使其现在存在。

    请注意,此获取或重建方法适用于 任何 损坏或丢失的对象:哈希 ID 在 每个 克隆中是全局唯一的,因此如果您可以 在其他克隆中找到对象,您可以从其他克隆中复制对象

    结论

    我将如何从这个混乱中修复 USB 密钥和其他 repo?

    最清晰的方法是使用其他克隆。查找同一存储库的未损坏克隆。制作该克隆的克隆,成为您新的“修复克隆”结果。向该新克隆添加来自损坏存储库的 new 对象(新标签、树、blob 和提交),这些对象本身未损坏。 (您可以直接复制它们,使用cp,或使用git cat-file -p <hash> | git hash-object -t <type> --stdin。)这样您只能从损坏的克隆中读取

    当您撞到损坏的物体时,尽可能多地恢复有用的数据,然后继续前进。

    结果将始终是具有尽可能多恢复数据的良好且有效的克隆并且您将确切地知道您恢复了什么以及丢失了什么。您甚至可以在提交时丢失某些文件(因为它们的内部 blob 对象已不可恢复地损坏):您可以在某处保存注释,可能使用 git notes 或可能只是在纸上,关于此,然后返回并重建您可以稍后,例如。

    这种方法往往缓慢而痛苦。您使用的方法(尝试就地修复损坏的克隆)更快、更容易,但可能会给您留下一些隐藏的问题(例如,丢失的提交,您只是不记得了,之后 一个您故意破坏的,因为它已损坏)。

    【讨论】:

    • 感谢您的详尽回复!我从中吸取了教训,我相信它对其他人会很有帮助。是否需要运行某种清理来清除孤立的损坏对象,或者传递git fsck 是否意味着将来不应该出现问题(例如,通过 fsck 意味着将来重新打包不应在孤立的损坏对象上失败)?
    • 如果git fsck 认为一切都很好,那么他们应该 很好。历史上存在git fsck 没有发现的问题。 (大多数都很小,例如意外允许包含带有前导零的mode 字符串的树对象,这将是不可能的,因为系统崩溃/删除驱动器类型损坏。)所以,不能完全保证,但相当扎实。
    【解决方案2】:

    [现在回答自己的问题,但我想接受一个真正有效的答案]

    • 计算机 1:
      • 在第一个 repo 上运行 git fsck 以冲突它没有损坏
      • 将 repo 文件夹复制到计算机 1 上的备份中
      • 在计算机 1 上提交任何内容(和/或如果只有你,可能会变基)
      • 推送到 USB 密钥(选项:事先在 USB 密钥上运行 git fsck;不知道如何在裸仓库上运行,所以我将其克隆到临时仓库...)
    • 计算机 2:
      • 将计算机 2 上损坏的 repo 文件夹复制到备份中
      • git clone 从 USB 密钥恢复 repo

    这显然不是答案,但目前有效(“足够好”),但解决此问题的正确方法可能会使社区受益。

    【讨论】:

      猜你喜欢
      • 2016-01-05
      • 1970-01-01
      • 2017-04-06
      • 2017-09-30
      • 2015-04-23
      • 1970-01-01
      • 2015-07-13
      • 2013-05-23
      • 2020-03-18
      相关资源
      最近更新 更多