如何恢复 git 存储库中损坏的对象(对于新手)?
我今天尝试打开我的存储库,但没有提交历史记录。我尝试的所有操作(git status、git log、git checkout...)都会引发有关损坏对象的错误。
我在线研究了这个问题,发现 文章,作者:Linus Torvalds,但在他发现损坏的链接 ID 时迷失了方向:我的文件 ID、树或 blob 都不与错误消息抛出的罪魁祸首 ID 匹配。
然后我回到关于恢复 "git 对象损坏的文章由于硬盘故障” 并且(在将罪魁祸首移开后)一直工作到
$ cat packed-refs
我的计算机说:cat: Packed-refs: No such file or directory
我跳过了该步骤并执行了
$ git fsck --full
并获得了适当的输出,但随后我应该将罪魁祸首(或者我所说的罪魁祸首,错误抛出的 sha1 ID)从备份存储库复制回主存储库,然后据我所知,将丢失的对象从备份存储库复制到主存储库中;我不想做任何太的事情,否则我可能会强迫一些我以后无法取消的事情。
所以我的问题是,我是否应该进行备份(哦,新手警报),或者是我解压 .pack 文件时发生的情况?我复制回来的“罪魁祸首”实际上是一个干净的文件,即没有损坏吗?
(我认为公平地告诉你,我最初对 Torvalds 文件中“git”和“fsck”之间的简单破折号感到困惑。所以我对此真的很陌生。)
BUG -LIST
原始错误:
$ 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
I tried to open my repository today and it came up with no commit history. Everything I tried (git status, git log, git checkout...) threw an error about a corrupt object.
I researched this problem online and found the article by Linus Torvalds, but got lost at the point where he found the broken link ID: none of my file IDs, tree or blob, match the culprit ID thrown by the error message.
I then returned to the article on recovering "git objects damaged by hard disk failure" and (after moving the culprit object out of the way) worked my way through until
$ cat packed-refs
at which point my computer said: cat: packed-refs: No such file or directory
I skipped that step and did the
$ git fsck --full
and got the appropriate output, but then I was supposed to copy the culprit (or what I was referring to as the culprit, the sha1 ID thrown by the error) from a backup repository back into the main repository, then copy the missing objects from the backup repository into the main repository, as far as I can tell; and I don't want to do anything too drastic or I might force something I can't unforce later.
So my question(s) is (are), was I supposed to have made a backup (ooh, newbie alert), or was that what happened when I unpacked the .pack file? And is the "culprit" I'm copying back actually a clean file, i.e. not corrupted?
(I think it only fair to tell you that I was initially confused by a simple dash in Torvalds' file between the "git" and "fsck." So I'm REALLY new at this.)
BUG-LIST
Original bug:
$ git status
fatal: object 016660b7605cfc2da85f631bbe809f7cb7962608 is corrupted
Bug after moving corrupt object:
$ 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
After moving the corrupted object back:
$ 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
After moving the file back out:
$ 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
After unpacking the .pack file:
$ 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,就这样吧。我们可以从第二条错误消息中看到您移动的损坏对象是提交。 (HEAD 指着它!)不幸的是,这意味着很难手动修复它。 (我所说的“困难”是指可能不可能,除非您能准确记住提交消息是什么以及提交的时间。)幸运的是,这确实意味着可以很容易地使用相同的文件内容恢复新的提交 - 您将只需要为其写一条新消息即可。
在开始之前,请查看
.git/HEAD
的内容 - 如果它是分支名称,请记住以供稍后使用。首先,我们需要弄清楚这个提交的父提交应该是什么。您可以使用 git reflog 来查看 HEAD 的 reflog,并找到提交 016660b 之前 HEAD 所在位置的 SHA1。它应该看起来像这样:
您可以复制 HEAD 先前位置的 SHA1,并检查该提交:
然后您可以在树中读取损坏的提交的内容:
然后提交!
现在,这里有一些关于您的分支机构应该发生什么的问题。如果 HEAD 指向一个分支(比如 master),而该分支又指向损坏的提交,我们肯定想修复这个问题:
如果还有其他分支包含损坏的提交,您也必须对它们进行一些恢复- 如果您需要帮助,请告诉我。
Okay, so. We can see from the second error message that the corrupt object which you moved was a commit. (HEAD was pointing to it!) Unfortunately, this means that it's hard to manually repair it. (By "hard" I mean likely impossible unless you can remember exactly what the commit message was and what time you made the commit.) Fortunately, this does mean that it's easy to resurrect a new commit with the same file contents - you'll just have to write a new message for it.
Before you start, have a look at the contents of
.git/HEAD
- if it's a branch name, remember that for later.First, we need to figure out what the parent of this commit should've been. You can use
git reflog
to look at the reflog of HEAD, and find the SHA1 of where HEAD was just before you made commit 016660b. It should look something like this:You can copy the SHA1 of the previous position of HEAD, and check out that commit:
Then you can read in the tree that your corrupted commit had:
And then commit!
Now, there's some question here about what should've happened to your branches. If HEAD was pointing to a branch (say master) which in turn pointed to the corrupted commit, we definitely want to fix that up:
If there are other branches which contained the corrupted commit, you'll have to do some restoration on them too - let me know if you need help with that.
FWIW,这里的答案比许多关于损坏的 git 存储库的其他问题上的绝望乐观的答案更实际 - 其中大多数都做出了毫无根据的假设,即可怜的 OP 可以“重新克隆”遥远的起源!唔。 但是。等一下。如果我是起源怎么办?
恐怖
故事开始于尝试运行一个简单的 git gc --aggressive 时发现,在我不知道的情况下,在某个时候我的完全本地的 git 存储库以某种方式发生了变化。完全崩溃了:它无法记录几个月前的任何内容,从而丢失了大部分历史记录,并且每当被要求 git fsck --full | 时都会发出喉声尖叫。 grep -v 悬挂。 git fsck 识别出多个对象丢失。
git-repair
:自 2014 年以来最大限度地减少可怕的体力劳动,在惊慌失措并发现很多问题的答案被过度投票的糟糕答案之后,只是说“只需从远程源重新克隆!” - 让我强调一下,我没有,因为我是起源 - 我发现
git-repair
,做了一个简单的sudo aptitude install git-repair
,并让它完成所有繁琐的自动化操作可能需要花费我几个小时的修复(请:在损坏的存储库的副本上运行[duh],没有--force
!) >这有助于减少 git fsck --full | 报告的恐怖数量grep -v 悬挂。但八月中旬之后的事情仍然遥不可及。
特别是,这一切似乎都围绕着一个无法检索的提交。我怎样才能恢复它?搜索 Stack Overflow 并没有多大帮助!
你有备份,对吧?
在这里,我很幸运能够从 11 月底开始获得备份。你备份了,对吧?就我而言,它是存储库的手动压缩(我的日常备份例程是一些可怕的增量
tar
东西,我从未实际测试过......咳嗽)......但是唷,这已经足够好了。它没有遭受我的实时回购所遭受的任何侮辱。但丢失的对象似乎并不仅仅存储在该备份的
.git/objects/XY/RESTOFHASHBLAHBLAHBLAH
中。这可能是因为它是提交,而不是文件。我不知道!git
对我来说是魔法,永远超出了我的理解能力。我只需要快速修复。这不是我们都在这里的原因吗?从备份中恢复对象(你有,对吧?)
现在有了备份,我有一个可笑的愚蠢想法,说“这不可能行得通!”,然后立即发现只需天真地运行 cp -fr /path/to/repo_backup/.git/objects/* /path/to/repo_git-repaired/.git/objects 到文件合并
.git/objects
目录将备份复制到我损坏的、已修复的存储库中的对应部分...努力恢复所有历史记录 - 回到良好的初始提交哈哈
。证明修复: git fsck --full 现在也很高兴(尽管有所有悬而未决的位)。然后,我将活动/损坏、部分修复和看似恢复的存储库的备份复制到单独的驱动器上,以防我再次需要其中任何一个。
在运行该方法和命令之前,您应该仔细检查它,或者也许找到一种我懒得想的更好的方法。我不知道。但对我来说,它拯救了我的仓库。关于事后猜测我所说的话......
无限组合中的无限免责声明
现在,显然所有这些都带有警告:你必须在损坏的存储库副本上尝试所有内容,阅读全部文档,请考虑比我更加小心(强制
cp
命令),并且不要让我对任何出错的地方负责*...但它给了你更好的东西尝试比“只是从远程源重新克隆!”,对吧?*
但是,如果一切顺利,那么一笔大笔捐款可能是合适的。 ;)如果有人需要我,我会怀疑地盯着我的磁盘驱动器的大致方向,希望能提出一个备份例程,不需要花费两位数的时间来恢复(如果有的话),甚至可能睡一会儿。
FWIW, here's an answer that is more practical than a lot of the hopelessly optimistic ones on other questions about corrupted
git
repos - most of which make the baseless assumption that the poor OP can 'just re-clone from the remote origin!' Hmm. But. Wait a second. What if I am the origin?The horror
The story begins when an attempt to run a simple
git gc --aggressive
revealed that, unbeknownst to me, at some point my - completely local -git
repo had somehow gotten completely hosed: It was unable to log anything beyond a few months ago, thereby losing the majority of its history, and screamed gutturally whenever asked togit fsck --full | grep -v dangling
. Several objects were identified as lost bygit fsck
.git-repair
: minimising terrifying manual labour since 2014After panicking and finding lots of questions with over-voted poor answers just saying 'just re-clone from the remote origin!' - which, let me belabour the point, I don't have because I am the origin - I found
git-repair
, did a simplesudo aptitude install git-repair
, and let it do all the tedious automatable fixes that would've probably taken me hours (please: run on a copy of your corrupted repo [duh], without--force
!)That helped reduce the amount of horror reported by
git fsck --full | grep -v dangling
. But things beyond the middle of August were still unreachable.In particular, this all seemed to centre around one commit that couldn't be retrieved. How could I recover it? Searching Stack Overflow wasn't much help!
You have a backup, right?
Here's where I was lucky enough to have a backup from the end of November. You take backups, right? In my case, it was a manual zip of the repo (my daily backup routine is some horrible incremental
tar
thing that I've never actually tested... a-cough)... but phew, it was good enough. It hadn't suffered whatever indignity had afflicted my live repo.But the missing object didn't seem to be simply stored in this backup's
.git/objects/XY/RESTOFHASHBLAHBLAHBLAH
. That's probably because it was a commit, not a file. I don't know!git
is wizardry to me, forever beyond my capacity to comprehend. I just needed a fix, fast. Isn't that why we're all here?Recover objects from a backup (which you have, right?)
With backup now in hand, I had a hilariously dumb idea, said 'there's no way this can work!', and immediately found that simply naively running
cp -fr /path/to/repo_backup/.git/objects/* /path/to/repo_git-repaired/.git/objects
to file-merge the.git/objects
directory of the backup into its counterpart in my corrupted,-somewhat-repaired repo... worked to recover all history - right back to good ol'initial commit lol
. Proving the fix:git fsck --full
was now happy too (notwithstanding all the dangling bits).I then took backups of the live/corrupted, partly repaired, and seemingly recovered repos onto a separate drive, in case I need any of them again.
You should double-check that methodology and command before you run it, or perhaps find a much better way that I'm too lazy to think of. I don't know. But for me, it saved my repo. And on the subject of second-guessing what I say...
Infinite disclaimers in infinite combinations
Now, obviously all of this comes with caveats: you must try everything on a copy of your corrupted repo, read all the documentation, consider being a bit more careful than I was (that forced
cp
command), and not hold me responsible or liable for absolutely anything that goes wrong*... but it gives you something better to try than 'just re-clone from the remote origin!', right?*
If, however, everything goes right, a large donation may be in order. ;)If anyone needs me, I'll be glaring suspiciously in the general direction of my disk drive, hopefully coming up with a backup routine that won't take double-digit hours to restore from (if at all), and maybe even getting some sleep.
我也有同样的问题。但是,通过更改服务器上 .git/objects 文件夹和子文件夹(递归地)的权限,我的问题得到了解决。比如:
我认为这不是你的问题,但就我而言,它已经解决了。
I had the same problem. However, my problem was resolved with changing permissions of the .git/objects folders and subfolders (recursively) on server. Something like:
I think that isn't your problem, but in my case it was resolved.