如何恢复被硬盘损坏损坏的Git对象?

时间:2021-12-01 00:02:48

I have had a hard disk failure which resulted in some files of a Git repository getting damaged. When running git fsck --full I get the following output:

我遇到了硬盘故障,导致Git仓库的一些文件被损坏。在运行git fsck时,我得到如下输出:

error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted

I have backups of the repository, but the only backup that includes the pack file has it already damaged. So I think that I have to find out a way to retrieve the single objects from different backups and somehow instruct Git to produce a new pack with only correct objects.

我有存储库的备份,但是包含包文件的唯一备份已经损坏了。因此,我认为我必须找到一种方法来从不同的备份中检索单个对象,并以某种方式指示Git生成一个只有正确对象的新包。

Can you please give me hints how to fix my repository?

你能告诉我如何修复我的仓库吗?

7 个解决方案

#1


78  

In some previous backups, your bad objects may have been packed in different files or may be loose objects yet. So your objects may be recovered.

在以前的一些备份中,您的坏对象可能已经被打包在不同的文件中,或者可能是松散的对象。所以你的物品可能会被回收。

It seems there are a few bad objects in your database. So you could do it the manual way.

在您的数据库中似乎有一些坏的对象。你可以用手工的方法。

Because of git hash-object, git mktree and git commit-tree do not write the objects because they are found in the pack, then start doing this:

因为git hashobject, git mktree和git committree不写对象,因为它们是在包中找到的,然后开始执行以下操作:

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(Your packs are moved out from the repository, and unpacked again in it; only the good objects are now in the database)

(您的包从存储库中移出,并在其中重新打包;只有好的对象现在在数据库中)

You can do:

你能做什么:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

and check the type of the object.

检查对象的类型。

If the type is blob: retrieve the contents of the file from previous backups (with git show or git cat-file or git unpack-file; then you may git hash-object -w to rewrite the object in your current repository.

如果类型是blob:从以前的备份中检索文件的内容(使用git show或git catt文件或git unpack-file);然后,可以在当前存储库中重新编写该对象。

If the type is tree: you could use git ls-tree to recover the tree from previous backups; then git mktree to write it again in your current repository.

如果类型是树:您可以使用git ls树来从以前的备份中恢复树;然后git mktree在当前存储库中再次编写它。

If the type is commit: the same with git show, git cat-file and git commit-tree.

如果类型是commit:与git显示、git文件和git提交树相同。

Of course, I would backup your original working copy before starting this process.

当然,在开始这个过程之前,我会备份您的原始工作副本。

Also, take a look at How to Recover Corrupted Blob Object.

另外,看看如何恢复被损坏的Blob对象。

#2


38  

Banengusk was putting me on the right track. For further reference, I want to post the steps I took to fix my repository corruption. I was lucky enough to find all needed objects either in older packs or in repository backups.

Banengusk让我走上了正确的道路。为了进一步的引用,我想要发布修复我的存储库损坏的步骤。我很幸运地找到了所有需要的对象,要么是旧包,要么是存储库备份。

# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD

$ cat .git/HEAD 
ref: refs/heads/master

$ ls .git/refs/heads/

$ cat .git/packed-refs 
# pack-refs with: peeled 
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master

$ git fsck --full 
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc

# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects

# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack

# Check reflogs...
$ git reflog

# ...then clean
$ git reflog expire --expire=0 --all

# Now garbage collect again
$ git gc       
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!

#3


13  

Try the following commands at first (re-run again if needed):

首先尝试以下命令(如果需要,重新运行):

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

And then you you still have the problems, try can:

然后你仍然有问题,试着:

  • remove all the corrupt objects, e.g.

    删除所有损坏的对象。

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • remove all the empty objects, e.g.

    删除所有空对象,例如:

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
    
  • check a "broken link" message by:

    查看“断开链接”信息:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    This will tells you what file the corrupt blob came from!

    这将告诉您什么文件损坏的blob来自!

  • to recover file, you might be really lucky, and it may be the version that you already have checked out in your working tree:

    要恢复文件,您可能非常幸运,它可能是您已经在工作树中签出的版本:

    git hash-object -w my-magic-file
    

    again, and if it outputs the missing SHA1 (4b945..) you're now all done!

    再一次,如果它输出丢失的SHA1 (4b945..),您现在都完成了!

  • assuming that it was some older version that was broken, the easiest way to do it is to do:

    假设这是一个旧版本,它被打破了,最简单的方法是:

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    and that will show you the whole log for that file (please realize that the tree you had may not be the top-level tree, so you need to figure out which subdirectory it was in on your own), then you can now recreate the missing object with hash-object again.

    这将向您显示该文件的整个日志(请注意,您所拥有的树可能不是*树,因此您需要找出它属于您自己的子目录),然后您可以再次使用hash-object重新创建丢失的对象。

  • to get a list of all refs with missing commits, trees or blobs:

    要得到所有未提交的refs的列表,树或blobs:

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    It may not be possible to remove some of those refs using the regular branch -d or tag -d commands, since they will die if git notices the corruption. So use the plumbing command git update-ref -d $ref instead. Note that in case of local branches, this command may leave stale branch configuration behind in .git/config. It can be deleted manually (look for the [branch "$ref"] section).

    使用常规的分支-d或标记-d命令,可能不可能删除一些refs,因为如果git注意到损坏,它们将会死。因此,使用管道命令git update-ref -d $ref。注意,在本地分支的情况下,这个命令可能会在.git/config中留下陈旧的分支配置。可以手动删除它(查找[分支“$ref”]部分)。

  • After all refs are clean, there may still be broken commits in the reflog. You can clear all reflogs using git reflog expire --expire=now --all. If you do not want to lose all of your reflogs, you can search the individual refs for broken reflogs:

    在所有的裁判都是干净的之后,仍然有可能在重鞭策中被破坏。您可以使用git reflog终止所有的reflogs——过期=现在—所有。如果你不想失去所有的reflogs,你可以搜索破碎的reflogs的个别参考:

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (Note the added -g option to git rev-list.) Then, use git reflog expire --expire=now $ref on each of those. When all broken refs and reflogs are gone, run git fsck --full in order to check that the repository is clean. Dangling objects are Ok.

    (注意,git rev-list中添加的-g选项。)然后,使用git reflog过期——过期=现在$ref。当所有破碎的refs和reflogs都消失后,运行git fsck——以检查存储库是否干净。晃来晃去的对象是好的。


Below you can find advanced usage of commands which potentially can cause lost of your data in your git repository if not used wisely, so make a backup before you accidentally do further damages to your git. Try on your own risk if you know what you're doing.

下面,您可以找到一些命令的高级用法,这些命令可能会导致git存储库中的数据丢失,如果不明智地使用,那么在意外地对您的git造成进一步损害之前,先进行备份。如果你知道自己在做什么,试试自己的风险。


To pull the current branch on top of the upstream branch after fetching:

取出后将当前分支拉到上游分支上:

$ git pull --rebase

You also may try to checkout new branch and delete the old one:

您还可以尝试签出新的分支并删除旧的分支:

$ git checkout -b new_master origin/master

To find the corrupted object in git for removal, try the following command:

要在git中查找被损坏的对象,请尝试以下命令:

while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done

For OSX, use sed -E instead of sed -r.

对于OSX,使用sed -E而不是sed -r。


Other idea is to unpack all objects from pack files to regenerate all objects inside .git/objects, so try to run the following commands within your repository:

其他的想法是将所有的对象从包文件中解压,以便在.git/对象中重新生成所有对象,所以尝试在您的存储库中运行以下命令:

$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak

If above doesn't help, you may try to rsync or copy the git objects from another repo, e.g.

如果上面没有帮助,您可以尝试rsync或从另一个repo复制git对象。

$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects

To fix the broken branch when trying to checkout as follows:

在尝试结帐时,修复损坏的分支如下:

$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

Try to remove it and checkout from upstream again:

试着把它从上游移走,再从上游签出:

$ git branch -D master
$ git checkout -b master github/master

In case if git get you into detached state, checkout the master and merge into it the detached branch.

如果git使您进入分离状态,签出主并将其合并到分离的分支中。


Another idea is to rebase the existing master recursively:

另一种方法是递归地重新建立现有的主服务器:

$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master

See also:

参见:

#4


2  

Here are the steps I followed to recover from a corrupt blob object.

下面是我从一个腐败的blob对象中恢复的步骤。

1) Identify corrupt blob

1)识别腐败blob

git fsck --full
  error: inflate: data stream error (incorrect data check)
  error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
  error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
  ...

Corrupt blob is 241091723c324aed77b2d35f97a05e856b319efd

腐败的团是241091723 c324aed77b2d35f97a05e856b319efd

2) Move corrupt blob to a safe place (just in case)

2)将腐败团移到安全的地方(以防万一)

mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3) Get parent of corrupt blob

3)得到腐败分子的父母。

git fsck --full
  Checking object directories: 100% (256/256), done.
  Checking objects: 100% (70321/70321), done.
  broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
              to    blob 241091723c324aed77b2d35f97a05e856b319efd

Parent hash is 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180.

父散列是0716831 e1a6c8d3e6b2b541d21c4748cc0ce7180。

4) Get file name corresponding to corrupt blob

4)获取与腐败blob对应的文件名。

git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
  ...
  100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz
  ...

Find this particular file in a backup or in the upstream git repository (in my case it is dump.tar.gz). Then copy it somewhere inside your local repository.

在备份或上游git存储库中找到这个特定的文件(在我的例子中是dump.tar.gz)。然后将其复制到本地存储库中的某个地方。

5) Add previously corrupted file in the git object database

5)在git对象数据库中添加先前损坏的文件。

git hash-object -w dump.tar.gz

6) Celebrate!

6)庆祝!

git gc
  Counting objects: 75197, done.
  Compressing objects: 100% (21805/21805), done.
  Writing objects: 100% (75197/75197), done.
  Total 75197 (delta 52999), reused 69857 (delta 49296)

#5


1  

Git checkout can actually pick out individual files from a revision. Just give it the commit hash and the file name. More detailed info here.

Git checkout实际上可以从修订中挑选出单个文件。只要给它提交哈希和文件名。更详细的信息。

I guess the easiest way to fix this safely is to revert to the newest uncommited backup and then selectively pick out uncorrupted files from newer commits. Good luck!

我认为最简单的解决方法是还原到最新的未启动备份,然后有选择地从新的提交中选择未损坏的文件。好运!

#6


1  

Here are two functions that may help if your backup is corrupted, or you have a few partially corrupted backups as well (this may happen if you backup the corrupted objects).

如果您的备份被损坏,或者您也有一些部分损坏的备份(如果您备份损坏的对象),以下两个功能可能会有所帮助。

Run both in the repo you're trying to recover.

在你试图恢复的repo中运行。

Standard warning: only use if you're really desperate and you have backed up your (corrupted) repo. This might not resolve anything, but at least should highlight the level of corruption.

标准警告:只有在你非常绝望的时候才使用,并且你已经备份了(损坏的)repo。这可能无法解决任何问题,但至少应该突显腐败的程度。

fsck_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git fsck --full --no-dangling 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null

and

unpack_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git unpack-objects -r < "$1" 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

for p in $1/objects/pack/pack-*.pack; do
    echo "$p"
    unpack_rm_corrupted "$p"
done

#7


0  

I have resolved this problem to add some change like git add -A and git commit again.

我已经解决了这个问题,以添加一些诸如git add -A和git提交的更改。

#1


78  

In some previous backups, your bad objects may have been packed in different files or may be loose objects yet. So your objects may be recovered.

在以前的一些备份中,您的坏对象可能已经被打包在不同的文件中,或者可能是松散的对象。所以你的物品可能会被回收。

It seems there are a few bad objects in your database. So you could do it the manual way.

在您的数据库中似乎有一些坏的对象。你可以用手工的方法。

Because of git hash-object, git mktree and git commit-tree do not write the objects because they are found in the pack, then start doing this:

因为git hashobject, git mktree和git committree不写对象,因为它们是在包中找到的,然后开始执行以下操作:

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(Your packs are moved out from the repository, and unpacked again in it; only the good objects are now in the database)

(您的包从存储库中移出,并在其中重新打包;只有好的对象现在在数据库中)

You can do:

你能做什么:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

and check the type of the object.

检查对象的类型。

If the type is blob: retrieve the contents of the file from previous backups (with git show or git cat-file or git unpack-file; then you may git hash-object -w to rewrite the object in your current repository.

如果类型是blob:从以前的备份中检索文件的内容(使用git show或git catt文件或git unpack-file);然后,可以在当前存储库中重新编写该对象。

If the type is tree: you could use git ls-tree to recover the tree from previous backups; then git mktree to write it again in your current repository.

如果类型是树:您可以使用git ls树来从以前的备份中恢复树;然后git mktree在当前存储库中再次编写它。

If the type is commit: the same with git show, git cat-file and git commit-tree.

如果类型是commit:与git显示、git文件和git提交树相同。

Of course, I would backup your original working copy before starting this process.

当然,在开始这个过程之前,我会备份您的原始工作副本。

Also, take a look at How to Recover Corrupted Blob Object.

另外,看看如何恢复被损坏的Blob对象。

#2


38  

Banengusk was putting me on the right track. For further reference, I want to post the steps I took to fix my repository corruption. I was lucky enough to find all needed objects either in older packs or in repository backups.

Banengusk让我走上了正确的道路。为了进一步的引用,我想要发布修复我的存储库损坏的步骤。我很幸运地找到了所有需要的对象,要么是旧包,要么是存储库备份。

# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD

$ cat .git/HEAD 
ref: refs/heads/master

$ ls .git/refs/heads/

$ cat .git/packed-refs 
# pack-refs with: peeled 
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master

$ git fsck --full 
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc

# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects

# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack

# Check reflogs...
$ git reflog

# ...then clean
$ git reflog expire --expire=0 --all

# Now garbage collect again
$ git gc       
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!

#3


13  

Try the following commands at first (re-run again if needed):

首先尝试以下命令(如果需要,重新运行):

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

And then you you still have the problems, try can:

然后你仍然有问题,试着:

  • remove all the corrupt objects, e.g.

    删除所有损坏的对象。

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • remove all the empty objects, e.g.

    删除所有空对象,例如:

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
    
  • check a "broken link" message by:

    查看“断开链接”信息:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    This will tells you what file the corrupt blob came from!

    这将告诉您什么文件损坏的blob来自!

  • to recover file, you might be really lucky, and it may be the version that you already have checked out in your working tree:

    要恢复文件,您可能非常幸运,它可能是您已经在工作树中签出的版本:

    git hash-object -w my-magic-file
    

    again, and if it outputs the missing SHA1 (4b945..) you're now all done!

    再一次,如果它输出丢失的SHA1 (4b945..),您现在都完成了!

  • assuming that it was some older version that was broken, the easiest way to do it is to do:

    假设这是一个旧版本,它被打破了,最简单的方法是:

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    and that will show you the whole log for that file (please realize that the tree you had may not be the top-level tree, so you need to figure out which subdirectory it was in on your own), then you can now recreate the missing object with hash-object again.

    这将向您显示该文件的整个日志(请注意,您所拥有的树可能不是*树,因此您需要找出它属于您自己的子目录),然后您可以再次使用hash-object重新创建丢失的对象。

  • to get a list of all refs with missing commits, trees or blobs:

    要得到所有未提交的refs的列表,树或blobs:

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    It may not be possible to remove some of those refs using the regular branch -d or tag -d commands, since they will die if git notices the corruption. So use the plumbing command git update-ref -d $ref instead. Note that in case of local branches, this command may leave stale branch configuration behind in .git/config. It can be deleted manually (look for the [branch "$ref"] section).

    使用常规的分支-d或标记-d命令,可能不可能删除一些refs,因为如果git注意到损坏,它们将会死。因此,使用管道命令git update-ref -d $ref。注意,在本地分支的情况下,这个命令可能会在.git/config中留下陈旧的分支配置。可以手动删除它(查找[分支“$ref”]部分)。

  • After all refs are clean, there may still be broken commits in the reflog. You can clear all reflogs using git reflog expire --expire=now --all. If you do not want to lose all of your reflogs, you can search the individual refs for broken reflogs:

    在所有的裁判都是干净的之后,仍然有可能在重鞭策中被破坏。您可以使用git reflog终止所有的reflogs——过期=现在—所有。如果你不想失去所有的reflogs,你可以搜索破碎的reflogs的个别参考:

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (Note the added -g option to git rev-list.) Then, use git reflog expire --expire=now $ref on each of those. When all broken refs and reflogs are gone, run git fsck --full in order to check that the repository is clean. Dangling objects are Ok.

    (注意,git rev-list中添加的-g选项。)然后,使用git reflog过期——过期=现在$ref。当所有破碎的refs和reflogs都消失后,运行git fsck——以检查存储库是否干净。晃来晃去的对象是好的。


Below you can find advanced usage of commands which potentially can cause lost of your data in your git repository if not used wisely, so make a backup before you accidentally do further damages to your git. Try on your own risk if you know what you're doing.

下面,您可以找到一些命令的高级用法,这些命令可能会导致git存储库中的数据丢失,如果不明智地使用,那么在意外地对您的git造成进一步损害之前,先进行备份。如果你知道自己在做什么,试试自己的风险。


To pull the current branch on top of the upstream branch after fetching:

取出后将当前分支拉到上游分支上:

$ git pull --rebase

You also may try to checkout new branch and delete the old one:

您还可以尝试签出新的分支并删除旧的分支:

$ git checkout -b new_master origin/master

To find the corrupted object in git for removal, try the following command:

要在git中查找被损坏的对象,请尝试以下命令:

while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done

For OSX, use sed -E instead of sed -r.

对于OSX,使用sed -E而不是sed -r。


Other idea is to unpack all objects from pack files to regenerate all objects inside .git/objects, so try to run the following commands within your repository:

其他的想法是将所有的对象从包文件中解压,以便在.git/对象中重新生成所有对象,所以尝试在您的存储库中运行以下命令:

$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak

If above doesn't help, you may try to rsync or copy the git objects from another repo, e.g.

如果上面没有帮助,您可以尝试rsync或从另一个repo复制git对象。

$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects

To fix the broken branch when trying to checkout as follows:

在尝试结帐时,修复损坏的分支如下:

$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

Try to remove it and checkout from upstream again:

试着把它从上游移走,再从上游签出:

$ git branch -D master
$ git checkout -b master github/master

In case if git get you into detached state, checkout the master and merge into it the detached branch.

如果git使您进入分离状态,签出主并将其合并到分离的分支中。


Another idea is to rebase the existing master recursively:

另一种方法是递归地重新建立现有的主服务器:

$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master

See also:

参见:

#4


2  

Here are the steps I followed to recover from a corrupt blob object.

下面是我从一个腐败的blob对象中恢复的步骤。

1) Identify corrupt blob

1)识别腐败blob

git fsck --full
  error: inflate: data stream error (incorrect data check)
  error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
  error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
  ...

Corrupt blob is 241091723c324aed77b2d35f97a05e856b319efd

腐败的团是241091723 c324aed77b2d35f97a05e856b319efd

2) Move corrupt blob to a safe place (just in case)

2)将腐败团移到安全的地方(以防万一)

mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3) Get parent of corrupt blob

3)得到腐败分子的父母。

git fsck --full
  Checking object directories: 100% (256/256), done.
  Checking objects: 100% (70321/70321), done.
  broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
              to    blob 241091723c324aed77b2d35f97a05e856b319efd

Parent hash is 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180.

父散列是0716831 e1a6c8d3e6b2b541d21c4748cc0ce7180。

4) Get file name corresponding to corrupt blob

4)获取与腐败blob对应的文件名。

git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
  ...
  100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz
  ...

Find this particular file in a backup or in the upstream git repository (in my case it is dump.tar.gz). Then copy it somewhere inside your local repository.

在备份或上游git存储库中找到这个特定的文件(在我的例子中是dump.tar.gz)。然后将其复制到本地存储库中的某个地方。

5) Add previously corrupted file in the git object database

5)在git对象数据库中添加先前损坏的文件。

git hash-object -w dump.tar.gz

6) Celebrate!

6)庆祝!

git gc
  Counting objects: 75197, done.
  Compressing objects: 100% (21805/21805), done.
  Writing objects: 100% (75197/75197), done.
  Total 75197 (delta 52999), reused 69857 (delta 49296)

#5


1  

Git checkout can actually pick out individual files from a revision. Just give it the commit hash and the file name. More detailed info here.

Git checkout实际上可以从修订中挑选出单个文件。只要给它提交哈希和文件名。更详细的信息。

I guess the easiest way to fix this safely is to revert to the newest uncommited backup and then selectively pick out uncorrupted files from newer commits. Good luck!

我认为最简单的解决方法是还原到最新的未启动备份,然后有选择地从新的提交中选择未损坏的文件。好运!

#6


1  

Here are two functions that may help if your backup is corrupted, or you have a few partially corrupted backups as well (this may happen if you backup the corrupted objects).

如果您的备份被损坏,或者您也有一些部分损坏的备份(如果您备份损坏的对象),以下两个功能可能会有所帮助。

Run both in the repo you're trying to recover.

在你试图恢复的repo中运行。

Standard warning: only use if you're really desperate and you have backed up your (corrupted) repo. This might not resolve anything, but at least should highlight the level of corruption.

标准警告:只有在你非常绝望的时候才使用,并且你已经备份了(损坏的)repo。这可能无法解决任何问题,但至少应该突显腐败的程度。

fsck_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git fsck --full --no-dangling 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null

and

unpack_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git unpack-objects -r < "$1" 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

for p in $1/objects/pack/pack-*.pack; do
    echo "$p"
    unpack_rm_corrupted "$p"
done

#7


0  

I have resolved this problem to add some change like git add -A and git commit again.

我已经解决了这个问题,以添加一些诸如git add -A和git提交的更改。