【问题标题】:How do you restore a corrupted object in a git repository (for newbies)?如何在 git 存储库中恢复损坏的对象(对于新手)?
【发布时间】:2011-04-06 12:49:46
【问题描述】:

我今天尝试打开我的存储库,但它没有提交历史记录。我尝试的所有操作(git status、git log、git checkout...)都抛出了关于损坏对象的错误。

我在网上研究了这个问题并找到了 Linus Torvalds 的 article,但在他发现损坏的链接 ID 时迷路了:我的文件 ID、树或 blob 都与错误引发的罪魁祸首 ID 不匹配消息。

然后我回到了关于恢复"git objects damaged by hard disk failure" 的文章并(在将罪魁祸首移开后)一直工作直到

$ cat packed-refs

此时我的电脑说:cat: packed-refs: No such file or directory 我跳过了这一步并做了

$ git fsck --full

并获得了适当的输出,但是我应该将罪魁祸首(或我所说的罪魁祸首,错误引发的 sha1 ID)从备份存储库复制回主存储库,然后复制据我所知,从备份存储库到主存储库中缺少对象;而且我不想做任何激烈的事情,否则我可能会强迫一些我以后无法解除的事情。

所以我的问题是(是),我是否应该进行备份(哦,新手警报),或者当我解压缩 .pack 文件时发生了什么?我复制回来的“罪魁祸首”实际上是一个干净的文件,即没有损坏吗?

(我认为公平地说,我最初对 Torvalds 文件中“git”和“fsck”之间的简单破折号感到困惑。所以我在这方面真的是新手.)

错误列表

原始错误:

$ git status
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

移动损坏对象后的错误:

$ git status
fatal: bad object HEAD
$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

$ git ls-tree 2c1033501b82e301d47dbf53ba0a199003af25a8
040000 tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd    folder1
040000 tree 33298295f646e8b378299191ce20b4594f5eb625    folder2
040000 tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2    folder3
040000 tree 4544967c6b04190f4c95b516ba8a86cab266a872    folder4

$ git ls-tree dec82bad6283fc7fcc869c20fdea9f8588a2f1b2
100644 blob 67bda6df733f6cd76fc0fc4c8a6132d8015591d8    fileA
100644 blob 4cb7272c9e268bfbd83a04e568d7edd87f78589c    fileB
100644 blob ce9e0f2cc4d3b656fa30340afbdfed47fe35f3ef    fileC

$ git ls-tree 4544967c6b04190f4c95b516ba8a86cab266a872
100644 blob d64fe3add8328d81b1f31c9dbd528956ab391fb6    fileD
100644 blob d1ebd7df7082abc5190d87caa821bf3edb7b68e8    fileE
100644 blob bb6cd264e47a3e5bc7beadf35ea13bac86024b02    ...
100644 blob 995d622b9012f4ef69921091d1e1a73f32aa94e6
100644 blob 9141dbd2b1c7931a6461195934b6599f5dfb485a 
100644 blob ab128da1d82907cd0568448dc089a7996d5f79d3
100644 blob 57b11a7eb408a79739d2bb60a0dc35c591340d18
100644 blob 118105291c1c6ca4a01744889ffafbb018bc7ed3
100644 blob 86b1dfda56d0603f16910228327751f869d16bdc
100644 blob 077fe0cddde0d0be9d0974f928f66815caca7b76
100644 blob c0b32fd0450f21994bdc53ea83d3cf0bccd74004
100644 blob 37b87a4d11453468c4ae04572db5d322cd2d1d80
100644 blob 79d39f8d4e57fa3a71664598a63b6dfd88149638
100644 blob ee07bbe3e8cb5d6bb79fb0cd52cfbc9bd830498d    files

$ git ls-tree 33298295f646e8b378299191ce20b4594f5eb625
100644 blob f9d6f45cd028aec97f761f00c5f4f2f6b50fb925    MoreFiles
100644 blob 0cb9eed1d0dd9214d54a03af1bda21f37b8c0d02
100644 blob 198e4f97ece735cce47b7e99b54f1b5fa99fabf5
100644 blob fc004212fa8e483e5a8ab35b508027c7a9a1cbfa
100644 blob 0c7d74c7a9a8337b4a9f20802b63d71d42287f89

$ git ls-tree 4a8b0b3747450085b1cd920c22ec82c18d9311bd
100644 blob 0320f5b23dd7cce677fac60b9ad03f418cff5c88    oneLASTfile

将损坏的对象移回后:

$ git log --raw --all
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted

将文件移出后:

$ git fsck --full`  
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

解压.pack文件后:

$ git log
fatal: bad object HEAD

$ cat packed-refs
cat: packed-refs: No such file or directory

$ git fsck --full
error: HEAD: invalid sha1 pointer 016660b7605cfc2da85f631bbe809f7cb7962608
error: refs/heads/RPG does not point to a valid object!
dangling tree 2c1033501b82e301d47dbf53ba0a199003af25a8
dangling blob 531aca5783033131441ac7e132789cfcad82d06d
dangling blob 74a47ff40a8c5149a8701c2f4b29bba408fa36f5
dangling blob b8df4d9751c0518c3560e650b21a182ea6d7bd5e
dangling blob fc2d15aead4bd0c197604a9f9822d265bb986d8b

【问题讨论】:

  • 您能否编辑您的问题并添加指向您提到的文章的链接,以便我们查看您所做的工作?我不确定您所说的“解压缩 .pack 文件”是什么意思,尽管这肯定不是备份 - 包文件只是一堆对象增量压缩到一个文件中。备份 git 存储库的一个好方法是克隆它!
  • 如果这个 SO 问题 stackoverflow.com/questions/801577/… 是您提到的第二篇文章,那么听起来与您提到的错误不同 - 除非您确实遇到了所有这些错误。您能否发布您遇到的确切错误?
  • 另外,在此之前您在 repo 中做的最后一件事是什么?万一这不是硬盘故障...
  • 我确实削减了一些步骤,主要是由于相同的错误或以前的功能。我还省略了一些输出类似于提到的文章的步骤,以及其他一些只是我与计算机摔跤的步骤(丑陋)。我做的最后一件事是提交到我所在的分支(不是主分支),用于文件夹 3 中的某些文件。紧接着,我关掉了电脑。如果有帮助,我的计算机有时有时不会完全关闭,并且当时也发生了这种不完全关闭。如有必要,我可以发布整个会话。
  • 顺便说一句,如果您在评论中添加了@Jefromi,SO 会通知我,以便我尽快回复您。 (如果您对我的回答发表评论,它会自动执行此操作;不需要它。)

标签: git recovery


【解决方案1】:

好的,所以。我们可以从第二条错误消息中看到,您移动的损坏对象是一个提交。 (HEAD 指着它!)不幸的是,这意味着很难手动修复它。 (“硬”是指可能不可能,除非你能准确记住提交消息是什么以及提交的时间。)幸运的是,这确实意味着用相同的文件内容重新提交新提交很容易——你会只需要为它写一条新消息。

在开始之前,请查看 .git/HEAD 的内容 - 如果是分支名称,请记住以备后用。

首先,我们需要弄清楚这个提交的父节点应该是什么。您可以使用git reflog 查看 HEAD 的 reflog,并在您提交 016660b 之前找到 HEAD 所在位置的 SHA1。它应该看起来像这样:

016660b HEAD@{n}: commit: <subject of commit>
1234abc HEAD@{n-1}: ...

您可以复制 HEAD 之前位置的 SHA1,并检查该提交:

git checkout 1234abc

然后您可以在树中读取损坏的提交:

git read-tree 2c1033501b82e301d47dbf53ba0a199003af25a8

然后提交!

git commit

现在,这里有一些关于您的分支应该发生什么的问题。如果 HEAD 指向一个分支(比如 master),而该分支又指向损坏的提交,我们肯定要修复它:

git branch -d master       # remove the original master branch
git checkout -b master     # recreate it here

如果有其他分支包含损坏的提交,您也必须对它们进行一些恢复 - 如果您需要帮助,请告诉我。

【讨论】:

  • 替换损坏的文件:$ git reflog fatal: bad object HEAD 损坏的文件到位:$ git reflog fatal: 对象 016660b7605cfc2da85f631bbe809f7cb7962608 已损坏我阅读了手册并尝试了:$ git reflog show HEAD@{ 1} 这给了我从 1 到 12 的活动,然后在 1 处重新启动并一直持续到我对存储库进行的初始拉取。这是命令的典型重启吗?
  • Continuing on... $ git checkout bcbd203 #which was HEAD@{1} fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted 我是否应该简单地将文件移出并再次尝试结帐?很抱歉这些 cmets 中没有用户友好的格式。我目前不知道有更好的方法来做到这一点。
  • @Humble:糟糕,抱歉。我实际上没有发生过这种情况,所以我在写未经测试的东西。我不知道 reflog 实际上试图读取对象!无论如何,只要你弄清楚之前的提交是什么,那部分就很好了。 (你也可以直接看.git/logs/HEAD
  • @Humble:对于结帐......是的,几乎所有你必须做的事情才能让它成功。将损坏的对象移出,如果不起作用...尝试checkout -f,然后尝试reset --hard &lt;SHA1&gt;...一旦有效,您应该可以继续。
  • 啊哈! Git 正在尽最大努力不让您丢弃任何信息——不幸的是,我们知道我们必须这样做。您将不得不以一种或另一种方式摆脱旧分支。如果git branch -f master; git checkout master不起作用,只需进入.git目录并自己将其拉出-删除refs/heads/masterlogs/refs/heads/master,然后正常创建。
【解决方案2】:

FWIW,对于有关损坏的git repos 的其他问题,这是一个比许多绝望乐观的答案更实用的答案-其中大多数都做出了毫无根据的假设,即可怜的 OP 可以“从远程重新克隆”起源!'唔。 但是。 等一下。如果我是起源呢?

恐怖

故事开始于尝试运行一个简单的 git gc --aggressive 时发现,在我不知道的情况下,我的 - 完全本地 - git repo 不知何故被完全淹没:它无法记录任何内容,除了几个几个月前,因此失去了它的大部分历史,每当被问到git fsck --full | grep -v dangling时,都会喉咙里尖叫。 git fsck 识别出多个对象丢失。

git-repair:自 2014 年以来将可怕的体力劳动降至最低

在惊慌失措并发现许多问题被过度投票的糟糕答案之后,只是说“只是从远程来源重新克隆!” - 让我再强调一下,我没有,因为我是起源 - 我找到了git-repair,做了一个简单的sudo aptitude install git-repair,让它完成所有繁琐的自动化修复可能会花费我几个小时(请:在损坏的 repo 的副本上运行 [duh],没有--force!)

这有助于减少git fsck --full | grep -v dangling 报告的恐怖程度。但是 8 月中旬之后的事情仍然无法实现。

特别是,这一切似乎都围绕着一个无法检索的提交。我怎样才能恢复它?搜索 Stack Overflow 并没有多大帮助!

你有备份,对吧?

这是我有幸从 11 月底开始备份的地方。你做备份,对吧?在我的情况下,它是 repo 的手动压缩(我的日常备份例程是一些可怕的增量 tar 我从未实际测试过的东西......咳嗽)......但是,它已经足够好了。它没有遭受任何影响我的现场回购的侮辱。

但丢失的对象似乎并没有简单地存储在此备份的.git/objects/XY/RESTOFHASHBLAHBLAHBLAH 中。那可能是因为它是一个提交,而不是一个文件。我不知道! git 对我来说是魔法,永远超出我的理解能力。我只需要快速修复。这不就是我们都在这里的原因吗?

从备份中恢复对象(你有,对吧?)

现在有了备份,我有了一个非常愚蠢的想法,说“这不可能!”,然后立即发现只是天真地运行cp -fr /path/to/repo_backup/.git/objects/* /path/to/repo_git-repaired/.git/objects文件合并.git/objects目录备份到我损坏的、稍微修复的 repo 中的对应项... 努力恢复所有历史记录 - 回到好的 ol' initial commit lol。证明修复:git fsck --full 现在也很高兴(尽管有所有悬空的位)。

然后,我将实时/损坏、部分修复和看似恢复的存储库备份到单独的驱动器上,以防我再次需要它们中的任何一个。

您应该在运行它之前仔细检查该方法和命令,或者找到一种我懒得想的更好的方法。我不知道。但对我来说,它保存了我的回购。关于我所说的事后猜测......

无限组合中的无限免责声明

现在,显然所有这些都带有警告:您必须在损坏的回购副本上尝试所有内容,阅读所有文档,考虑比我更小心一点(这迫使@ 987654339@ 命令),而不是让我对任何出错的事情负责或承担任何责任*...但它为您提供了比“只是从远程来源重新克隆!”更好的尝试,对吧?

* 但是,如果一切顺利正确,大笔捐款可能是有必要的。 ;)

如果有人需要我,我会怀疑地盯着我的磁盘驱动器的大致方向,希望能提出一个备份程序,不需要花费两位数的时间来恢复(如果有的话),也许甚至可以睡一觉。

【讨论】:

  • 您好,无法使用 git-repair 命令,我在 mac 上尝试了 'git git-repair' 'git-repair',没有任何效果,请帮助
  • 正如我的帖子中提到的,如果您没有安装git-repair,当然它不会起作用。我不了解 macOS,但假设您可以通过 Homebrew 等包管理器获得它。或者,如果没有,很可能是某个地方的某个人编译了它并在他们自己的网站上提供了下载。你只需要寻找它。
  • 我已经克隆,构建并安装在我的mac上,但不知道使用它的命令
  • 那么阅读文档?我不确定你想让我怎么做。
【解决方案3】:

我遇到了同样的问题。但是,通过更改服务器上 .git/objects 文件夹和子文件夹(递归)的权限,我的问题得到了解决。比如:

chmod -R 770 .git/objects

我认为这不是你的问题,但就我而言,它已经解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 2014-10-21
    • 2011-08-11
    • 2013-09-11
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多