如何修复损坏的git存储库?

时间:2013-09-07 23:19:32

标签: git

我把我的repo克隆到我的ubuntu一个文件夹到一台新机器上,我得到了这个:

christopher@christopher-laptop:~/source/personal$ git clone ~/Ubuntu\ One\ Side\ Work/projects.git/
Cloning into 'projects'...
done.
fatal: unable to read tree 29a422c19251aeaeb907175e9b3219a9bed6c616
christopher@christopher-laptop:~/source/personal$ 

所以我试着看看这里提出的许多其他问题,其中大多数人都说要运行git fsck --full,然后当我尝试时我会得到这个。

christopher@christopher-laptop:~/Ubuntu One Side Work/projects.git$ git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (447/447), done.
broken link from  commit 235ae1f48701d577d71ebd430344a159e5ba4881
              to  commit 984c11abfc9c2839b386f29c574d9e03383fa589
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    blob 25a742dff0a403b2b3884f2ffddf63eb45721fac
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    blob dd4e97e22e159a585b20e21028f964827d5afa4e
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    tree 29a422c19251aeaeb907175e9b3219a9bed6c616
broken link from    tree 632a9cf0ef9fccea08438b574e2f1c954f4ff08b
              to    tree 8084e8e04d510cc28321f30a9646477cc50c235c
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob a0daa0c1567b55d8de2b4d7a3bc010f58c047eab
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob e9052d35bfb6d30065b206fc43f4200a04d5281b
broken link from    tree 774b5b4157b4caae1c6cad96c8eaf5d4eba2c628
              to    blob 1a3a5e4dd2502ac121c22f743c4250e254a94eeb
broken link from    tree 4aa336dc1a5838e8918e03b85580069d83f4ad09
              to    tree 8cc55ec952dc192a233e062201d1e7e873ac3db0
broken link from    tree e5674a91a53e15575a1f3bf5786bc5cc719fb483
              to    blob 4a994e1e7bb7ce28dcec98bad48b9a891d7dec51
broken link from    tree e5674a91a53e15575a1f3bf5786bc5cc719fb483
              to    blob ac033bf9dc846101320c96a5ce8aceb8c96ec098
broken link from    tree 252ab84542264e1589576b6ee51e7a31e580a0e2
              to    tree 2069041cd5950e529e2991d37b7290ec021d90d4
broken link from    tree 2d4964aa4d4f5d8c7228518ce72ef6a63f820c6d
              to    blob d83690e1b9a6bdd8a08754b38231799acefcb2ab
broken link from    tree c7192e82fc581bd6448bda1a25e8729bdac5f4ff
              to    blob 30d54d47ae82add1917ca173d42e58b396df580b
broken link from    tree 7c66306901fc71389623286936cef172d4ffe408
              to    blob bc7e05d705401273b1df4e939de0f540597c0931
broken link from    tree 0940f5fd227d4c84d6e6749d872db50a4522ae3a
              to    tree 923767594ac22023e824948d65622fe5b407d1a1
broken link from    tree 8eadcd2a971e8357d24f0d80f993d2963452209f
              to    blob 2598bde3dc8cb80ee49510b8159344004b88645f
broken link from    tree ffa302dd0d969172ef23caeefe856ab2f57a4e4d
              to    blob d6925fa431be1ac585bf9a481e98f75107a6e6fb
broken link from    tree 7045b8870a49ce30a2027537a96d73d162bda773
              to    blob 25688652dea26f61f576ca1b52b9d1a18fbfd01d
broken link from    tree 37e4705d34bd440ce681ae32ae9a180a13256d72
              to    tree 246f564d4cee53339b8a4244f3173b61caa518eb
missing blob d6925fa431be1ac585bf9a481e98f75107a6e6fb
missing blob ac033bf9dc846101320c96a5ce8aceb8c96ec098
missing tree 29a422c19251aeaeb907175e9b3219a9bed6c616
missing tree 8084e8e04d510cc28321f30a9646477cc50c235c
missing blob 30d54d47ae82add1917ca173d42e58b396df580b
missing tree 8cc55ec952dc192a233e062201d1e7e873ac3db0
missing blob e9052d35bfb6d30065b206fc43f4200a04d5281b
dangling tree 4b26e95db542c72ac4a22ec25abe38fb2de79752
missing blob d83690e1b9a6bdd8a08754b38231799acefcb2ab
missing blob 25a742dff0a403b2b3884f2ffddf63eb45721fac
missing tree 923767594ac22023e824948d65622fe5b407d1a1
missing blob 25688652dea26f61f576ca1b52b9d1a18fbfd01d
missing blob 2598bde3dc8cb80ee49510b8159344004b88645f
dangling tree 3a683869f1bb0c1634de75700c316b3b36570dbd
dangling blob 4098d30843380d798a811f1aa9a02994f0dbbb27
missing tree 2069041cd5950e529e2991d37b7290ec021d90d4
missing blob 4a994e1e7bb7ce28dcec98bad48b9a891d7dec51
missing blob 1a3a5e4dd2502ac121c22f743c4250e254a94eeb
missing blob a0daa0c1567b55d8de2b4d7a3bc010f58c047eab
dangling tree 6c7b5162aa7a303fa3fe8dc393c5da564e309521
missing commit 984c11abfc9c2839b386f29c574d9e03383fa589
missing blob bc7e05d705401273b1df4e939de0f540597c0931
missing blob dd4e97e22e159a585b20e21028f964827d5afa4e
missing tree 246f564d4cee53339b8a4244f3173b61caa518eb
dangling commit a01f5c1e5315dc837203d6dee00d3493be9c5db9

看起来真的很糟糕。当我做git log | head时,我得到了这个

christopher@christopher-laptop:~/Ubuntu One Side Work/projects.git$ git log | head
error: Could not read 984c11abfc9c2839b386f29c574d9e03383fa589
fatal: Failed to traverse parents of commit 235ae1f48701d577d71ebd430344a159e5ba4881
commit 2fb0d2d0643b445440f01b164f11ee9ee71fca48
Author: christopher <christopher@christopher.christopher>
Date:   Wed Aug 7 15:51:42 2013 -0400

    finishing chapter 7

此处的其他问题曾说过./git/refs/heads/master。这是一个简单的仓库,refs/heads/存在,但refs/heads/master没有。裸仓库中的HEAD说ref: refs/heads/master虽然

packed-refs确实这么说

# pack-refs with: peeled 
2fb0d2d0643b445440f01b164f11ee9ee71fca48 refs/heads/master

还有其他问题建议运行git reflog,当我运行时没有显示输出。

所以我真的不知道该怎么做。应该采取什么策略?是否可以在8月7日将头重置为最后一次提交

修改

执行git日志并转到屏幕输出的底部显示:

commit 996e03b949aea176238e3c7a8452700bbb987ac9
Author: christopher <christopher@christopher>
Date:   Wed Jul 3 23:00:44 2013 -0400

    many many changes
error: Could not read 984c11abfc9c2839b386f29c574d9e03383fa589
fatal: Failed to traverse parents of commit 235ae1f48701d577d71ebd430344a159e5ba4881

这似乎阻止了git prune的工作

14 个答案:

答案 0 :(得分:55)

作为CodeGnome的最后一个选项的替代方案,如果只有本地存储库已损坏,并且您知道该遥控器的网址,则可以使用此方法重新设置.git以匹配该遥控器(替换{{} 1}}使用远程网址):

${url}

这使您的工作树完好无损,只会影响git的簿记 我最近也做了a bash script for this very purpose  (附录A),围绕此操作包含了一些安全性。

注意:

如果您的repo有子模块,这个过程会以某种方式弄乱它们,我到目前为止找到的唯一解决方案是删除它们然后使用mv -v .git .git_old && # remove old git git init && # initialise new repo git remote add origin "${url}" && # link to old repo git fetch && # get old history git reset origin/master --mixed # force update to old history (或重新克隆repo,但似乎< em>太激烈了。)

附录A - 完整脚本

git submodule update --init

答案 1 :(得分:51)

TL; DR

Git并不像你想象的那样存储历史。它基于祖先链在运行时计算历史记录。如果你的祖先缺少blob,树或提交,那么你可能无法完全恢复你的历史。

从备份中恢复丢失的对象

您可以尝试的第一件事是从备份中恢复丢失的项目。例如,查看您是否将提交的备份存储为.git/objects/98/4c11abfc9c2839b386f29c574d9e03383fa589。如果是这样,你可以恢复它。

如果提交已经打包并且您希望将其返回到松散的对象以进行存储库操作,您可能还需要查看git-verify-packgit-unpack-objects。< / p>

手术切除

如果您无法从备份中替换丢失的项目,则可以删除丢失的历史记录。例如,您可以检查您的历史记录或reflog以查找提交的祖先984c11abfc9c2839b386f29c574d9e03383fa589。如果你发现一个完整,那么:

  1. 将您的Git工作目录复制到某处的临时目录。
  2. 对未损坏的提交执行硬重置。
  3. 将当前文件复制回Git工作树,但请确保不要复制.git文件夹!
  4. 提交当前工作树,并尽力将其视为对所有遗失历史记录的压缩提交。
  5. 如果它有效,你当然会失去介入的历史。此时,如果您有一个工作历史记录日志,那么修剪所有无法访问的提交和对象的历史记录和reflog是个好主意。

    完全恢复和重新初始化

    如果您的存储库仍然存在损坏,那么希望您拥有可以从中还原的未损坏的备份或克隆。如果没有,但您当前的工作目录包含有效文件,那么您可以随时重新初始化Git。例如:

    rm -rf .git
    git init
    git add .
    git commit -m 'Re-initialize repository without old history.'
    

    这很激烈,但如果您的存储库历史记录真的无法恢复,那么它可能是您唯一的选择。 YMMV。

答案 2 :(得分:5)

这是一个脚本(bash),用于自动化@CodeGnome的第一个解决方案,从备份恢复(从损坏的仓库的顶层运行)。备份不需要完成,只需要缺少对象。

git fsck 2>&1 | grep -e missing -e invalid | awk '{print $NF}' | sort -u |
    while read entry; do
        mkdir -p .git/objects/${entry:0:2}
        cp ${BACKUP}/objects/${entry:0:2}/${entry:2} .git/objects/${entry:0:2}/${entry:2}
    done

答案 3 :(得分:5)

如果你配置了一个遥控器并且你不关心丢失一些未按下的代码,你可以这样做:

git fetch && git reset --hard

答案 4 :(得分:3)

如果你绝望,你可以试试这个:

git clone ssh://me@my.git.server/path/to/project destination --depth=1

它会获取您的数据,但您将丢失历史记录。我在我的回购邮件上试用了--depth=10,但--depth=50给了我失败。

答案 5 :(得分:3)

在尝试本页描述的任何修补程序之前,我建议您复制一份repo并仅处理此副本。然后在最后,如果您可以修复它,将其与原始文件进行比较,以确保您在修复过程中没有丢失任何文件。

另一个对我有用的选择是使用以下方法将git head和index重置为之前的状态:

git reset --keep

您也可以通过打开Git GUI并选择每个“分阶段更改”并单击“取消更改更改”来手动执行相同的操作。当一切都没有进入时,您现在应该能够压缩数据库,检查数据库并提交。

我也尝试了以下命令,但它们对我不起作用,但它们可能适合您,具体取决于您所拥有的问题:

git reset --mixed
git fsck --full
git gc --auto
git prune --expire now
git reflog --all

最后,为了避免这种同步问题损坏您的git索引(可能发生在DropBox,SpiderOak或任何其他云盘上),您可以执行以下操作:

  1. 使用:.git将您的git bundle create my_repo.git --all文件夹转换为单个“捆绑”git文件,然后它应该像以前一样工作,但因为一切都在一个文件,你不会冒同步破坏你的git仓库的风险。
  2. 禁用即时同步:SpiderOak允许您将检查更改的计划设置为“自动”(这意味着它可以尽快监控文件更改,这要归功于操作系统通知)。这很糟糕,因为它会在您进行更改后立即开始上传更改,然后下载更改,因此可能会删除您刚刚进行的最新更改。解决此问题的解决方案是将更改监视延迟设置为5分钟或更长时间。这也解决了即时保存记笔记应用程序(如Notepad ++)的问题。

答案 6 :(得分:2)

我遇到了同样的问题,所以我用备份版本替换了“.git”文件夹,但由于.gitconfig文件已损坏,它仍无法正常工作。我的笔记本电脑上的BSOD损坏了它。我用以下代码替换它,sourcetree恢复了我的所有存储库。

[user]
name = *your username*
email = *your email address*
[core]
autocrlf = true
excludesfile = C:\\Users\\*user name*\\Documents\\gitignore_global.txt

我不知道这是否会对任何人有所帮助,但这只是另一种对我有用的解决方案。

答案 7 :(得分:1)

在我的情况下,我正在从我的电脑中已有的源代码创建存储库,并且出现了错误。我删除了.git文件夹并再次完成所有操作并且它有效:)

答案 8 :(得分:1)

我尝试移走0字节的目标文件,然后再次从远程获取它们,并且有效:

find . -type f -size 0 -exec mv {} /tmp \;
git fetch

它从远程获取了丢失的对象,并允许我继续工作而无需重新初始化整个存储库。

答案 9 :(得分:1)

我想在以上Zoey Hewil出色的answer下添加它作为评论,但是我目前没有足够的代表这样做,因此我必须在此处添加它并赞扬她的工作:P

如果您正在使用Poshgit并感到异常懒惰,则可以使用以下内容从git配置中自动提取URL,并使轻松工作变得更加轻松。标准警告适用于在副本上进行测试/首先备份本地存储库,以防其在您面前爆炸。

$config = get-content .git\config
$url = $config -match " url = (?<content>.*)"
$url = $url.trim().Substring(6)
$url

move-item -v .git .git_old;
git init;
git remote add origin "$url";
git fetch;
git reset origin/master --mixed

答案 10 :(得分:1)

最近在Ubuntu 18.04.3下使用git版本2.7.1遇到了类似的问题。这是我的做法:

sudo apt install git-repair
git-repair  # fix a broken git repository
or
git-repair --force  # force repair, even if data is lost
git fsck  # to verify it was fixed

大多数情况下,恢复过程是成功的

答案 11 :(得分:0)

快速方法,如果您对当前项目进行了更改并且不想丢失它,请将当前项目移到某个位置,将项目从github克隆到此文件夹,然后进行一些更改,然后再次尝试提交。 或者只是删除该存储库并再次克隆它,它对我有效。

答案 12 :(得分:0)

删除索引并重新设置

rm -f .git/index
git reset

答案 13 :(得分:-3)

此命令对我有用:

$ git reset --mixed