我怎样才能恢复HEAD ^'S树? [英] How can I recover HEAD^'S tree?

查看:165
本文介绍了我怎样才能恢复HEAD ^'S树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr:是否有可能恢复 HEAD ^ 的树,如果它被删除并且没有被预先推送,并且其他东西都是完整?



我不小心删除了部分 .git 。我并不完全确定缺少什么。



在发现 git push 不起作用时,我跑了 git fsck

 检查对象目录:100%(256/256 ),完成。 
检查对象:100%(1265/1265),完成。从提交ccfe9502e24d2b5195008005d83155197a2dca25
到树0580c3675560cbfd3f989878a9524e35f53f08e9
。从提交ccfe9502e24d2b5195008005d83155197a2dca25
断开的链接提交f3419f630546ba02baf43f4ca760b02c0f4a0e6d
到树29616dfefd2bff59b7fb3177e99b4a1efc7132fa
损坏的链接提交0bca9b3a9f1dd9106922f5b4ec59cdc00dd6c049
$ B断链从树6d33d35870281340c7c2f86c6d48c8f133b836bb
$ b断链成团块226d8a10a623acd943bb8eddd080a5929f3ccb2c
断开的链接从提交db238d4a52ee8f18a04c038809bc6587d7643438
到树0b69ab3f6940a04684ee8c0c423ae7da89de749c
缺少树0580c3675560cbfd3f989878a9524e35f53f08e9
悬挂承诺05512f9ac09d932e7d9a11d490c8a2f117c0ca11
缺少树29616dfefd2bff59b7fb3177e99b4a1efc7132fa
dangling commit 578464dde7d7b8628f77e536b4076cfa491d7602
缺少blob 5d351b568abb734605ca4bf446e13c fd87ca9ce8
缺少树0b69ab3f6940a04684ee8c0c423ae7da89de749c
缺少承诺0bca9b3a9f1dd9106922f5b4ec59cdc00dd6c049
晃来晃去的blob d53a9d0f3364b648edbc4beede022e4594a84c35
丢失一滴23db34f729a88c5f5f7fe6e281921f1334f493d1
悬挂承诺8dcbde55462ca0c29e0ca339a49db95b43188ef1
悬挂一滴e59b25b9675625d0e6b8abfa37e955ab46493fd9
丢失一滴226d8a10a623acd943bb8eddd080a5929f3ccb2c
悬空提交85fdaaa579cf1ae2a8874e3e1f3c65d68b478179
悬空提交075e9d72e90cc8bf3d960edd8376aaae0847f916
缺失的斑点83fec2ff8cfcaaa06c96917b6973ace96301e932
悬空提交a88e18e1c102d909361738fd70137b3f4a1c7496
悬空团块9c6f61e0acffe2a1f5322cd2b72c181e95e9de75
悬空提交ca9fe0dd3123a731fc310b2a2285b00ef673de79


$ b因此,我的假设是我只是错过了一些可以从GitHub中恢复的信息。我的下意识的反应是运行 git fetch ,但返回时没有输出,因为它认为没有什么新的获取。



我尝试了几个方法解开 .git / objects / pack / pack-ea43d1db155e4502c2250ec1d4608843715c8b1f.pack ,但它从来没有奏效。例如:

 %git clone --mirror git://github.com/strugee/dots.git#返回裸回购
克隆到裸仓库'dots.git'...
remote:计数对象:1331,完成。
remote:压缩对象:100%(23/23),完成。
remote:共计1331(delta 12),重用0(delta 0)
接收对象:100%(1331/1331),402.31 KiB | 197.00 KiB / s,完成。
解决三角洲问题:完成100%(454/454)。
检查连通性...完成。
%ls dots.git
config描述HEAD钩子信息对象packed-refs refs
%mkdir git-tmp; cd git-tmp
%git init
%git unpack-objects< ../dots.git/objects/pack/pack-ea43d1db155e4502c2250ec1d4608843715c8b1f.pack
错误:膨胀:数据流错误(不正确的数据检查)
错误:膨胀返回-3

我每次都遇到这个错误。 (请记住:它是一个 - 镜像,所以它是GitHub的精确副本 - 对吗?它怎么会被损坏呢? )



最后,我意识到我并没有真正需要来解压packfile文件。我可以将它复制回原始的回购库,Git会把它捡回来。所以:

 %cd ../configs 
%cp ../dots.git/objects/pack/pack -ea43d1db155e4502c2250ec1d4608843715c8b1f。* .git / objects / pack /

这似乎是个诀窍。大部分。

 %git fsck 
检查对象目录:100%(256/256),done。
检查对象:100%(2596/2596),完成。从提交db238d4a52ee8f18a04c038809bc6587d7643438
到树0b69ab3f6940a04684ee8c0c423ae7da89de749c
悬挂
断开的链接提交05512f9ac09d932e7d9a11d490c8a2f117c0ca11
悬挂承诺578464dde7d7b8628f77e536b4076cfa491d7602
丢失一滴5d351b568abb734605ca4bf446e13cfd87ca9ce8
缺少树0b69ab3f6940a04684ee8c0c423ae7da89de749c
晃来晃去的blob d53a9d0f3364b648edbc4beede022e4594a84c35
悬空提交8dcbde55462ca0c29e0ca339a49db95b43188ef1
悬空提交85fdaaa579cf1ae2a8874e3e1f3c65d68b478179
悬空提交075e9d72e90cc8bf3d960edd8376aaae0847f916
缺失的斑点83fec2ff8cfcaaa06c96917b6973ace96301e932
悬空提交a88e18e1c102d909361738fd70137b3f4a1c7496
悬空提交ca9fe0dd3123a731fc310b2a2285b00ef673de79

正如您所看到的那样,修复了除了一个缺失链接外的所有链接。事实证明, db238d 是一个提交的id(碰巧是 HEAD ^ ),我没有但推动。我是否正确地认为这个仓库中的最后两个提交是不可恢复的,我将需要重新创建那些提交的内容?我在这种情况下做出了正确的决定吗? 解决方案

试试 git fetch-pack 来恢复其他存储库中可用的缺失对象。下面的指令。



为恢复unpushed提交,特别是HEAD ^ 1,我将以

  git diff-tree -r HEAD〜2 ^ {tree} HEAD ^ {tree} 



你会得到一个所有已经改变的树木/斑点和它们的SHA(其中包括来自HEAD和HEAD ^ 1的变化)的列表。根据有多少信息可用,您可以重新创建所有缺少的树中的一部分。但缺失的blob更麻烦。



使用 git fetch-pack



故意损坏的存储库

  me @ myvm:/scratch/corrupt/.git(GIT_DIR! objects / 
me @ myvm:/scratch/corrupt/.git/objects(GIT_DIR!)$ ll
total 20
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 20
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 22
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 25
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 info
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 pack
me @ myvm:/scratch/corrupt/.git/objects(GIT_DIR!)$ rm -rf 22

$ p
$ b $ p $



me @ myvm:/scratch/corrupt/.git/objects(GIT_DIR!)$ cd ../../
@ myvm:/ scratch / corrupt(master)$ git status
致命错误:bad对象HEAD

恢复丢失的对象

  me @ myvm:/ scratch / corrupt(master)$ git fetch-pack --al l $(git config --get remote.origin.url)
错误:refs / heads / master没有指向一个有效的对象!
错误:refs / remotes / origin / HEAD不指向有效的对象!
错误:refs / remotes / origin / master没有指向有效的对象!
错误:refs / heads / master没有指向一个有效的对象!
错误:refs / remotes / origin / HEAD不指向有效的对象!
错误:refs / remotes / origin / master没有指向有效的对象!
remote:计数对象:3,完成。
remote:合计3(delta 0),重用0(delta 0)
解包对象:100%(3/3),完成。
22ecde746be79c65b27a5cf1dc421764d8ff6e17 HEAD
22ecde746be79c65b27a5cf1dc421764d8ff6e17 refs / heads / master
my @ myvm:/ scratch / corrupt(master)$ git status
在分支master上
您的分支是up-与'origin / master'最新。
没有提交,工作目录干净

缺少对象恢复

  me @ myvm:/ scratch / corrupt(master)$ ll .git / objects / 
total 20
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 20
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:05 22
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 25
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 info
drwxrwxr-x 2 andrewc warp 4096 Oct 7 06:03 pack
me @ myvm:/ scratch / corrupt(master)$


me @ myvm:/ scratch / corrupt(master)$ git status
在分支主机上
您的分支是'origin / master'的最新版本。
没有提交,工作目录干净

如果您最终处于可以找到一个破碎的树对象和一个破碎的斑点对象,你可以手动恢复这些对象。您可以为任何blob git cat-file -p BLOB_SHA ,这会转储内容。如果你能通过查看文件的内容来找出可以帮助你恢复文件的文件。同样, git cat-file -p TREE_SHA 会转储树,它告诉你文件名和blob SHA。此时,您将尝试手动构建树并从可能的部分数据提交对象。如果您的HEAD提交是确定的,那么您只是遗漏了历史记录,并且至少应该覆盖最近的状态。


tl;dr: is it possible to recover HEAD^'s tree if it is deleted and not pushed beforehand and if everything else is intact?

I accidentally deleted part of my .git. I'm not entirely sure what's missing.

Upon discovering that git push didn't work, I ran a git fsck:

Checking object directories: 100% (256/256), done.
Checking objects: 100% (1265/1265), done.
broken link from  commit f3419f630546ba02baf43f4ca760b02c0f4a0e6d
              to    tree 29616dfefd2bff59b7fb3177e99b4a1efc7132fa
broken link from  commit ccfe9502e24d2b5195008005d83155197a2dca25
              to    tree 0580c3675560cbfd3f989878a9524e35f53f08e9
broken link from  commit ccfe9502e24d2b5195008005d83155197a2dca25
              to  commit 0bca9b3a9f1dd9106922f5b4ec59cdc00dd6c049
broken link from    tree 6d33d35870281340c7c2f86c6d48c8f133b836bb
              to    blob 226d8a10a623acd943bb8eddd080a5929f3ccb2c
broken link from  commit db238d4a52ee8f18a04c038809bc6587d7643438
              to    tree 0b69ab3f6940a04684ee8c0c423ae7da89de749c
missing tree 0580c3675560cbfd3f989878a9524e35f53f08e9
dangling commit 05512f9ac09d932e7d9a11d490c8a2f117c0ca11
missing tree 29616dfefd2bff59b7fb3177e99b4a1efc7132fa
dangling commit 578464dde7d7b8628f77e536b4076cfa491d7602
missing blob 5d351b568abb734605ca4bf446e13cfd87ca9ce8
missing tree 0b69ab3f6940a04684ee8c0c423ae7da89de749c
missing commit 0bca9b3a9f1dd9106922f5b4ec59cdc00dd6c049
dangling blob d53a9d0f3364b648edbc4beede022e4594a84c35
missing blob 23db34f729a88c5f5f7fe6e281921f1334f493d1
dangling commit 8dcbde55462ca0c29e0ca339a49db95b43188ef1
dangling blob e59b25b9675625d0e6b8abfa37e955ab46493fd9
missing blob 226d8a10a623acd943bb8eddd080a5929f3ccb2c
dangling commit 85fdaaa579cf1ae2a8874e3e1f3c65d68b478179
dangling commit 075e9d72e90cc8bf3d960edd8376aaae0847f916
missing blob 83fec2ff8cfcaaa06c96917b6973ace96301e932
dangling commit a88e18e1c102d909361738fd70137b3f4a1c7496
dangling blob 9c6f61e0acffe2a1f5322cd2b72c181e95e9de75
dangling commit ca9fe0dd3123a731fc310b2a2285b00ef673de79

So my assumption is that I'm merely missing some information that can be recovered from GitHub. My knee-jerk reaction was to run git fetch, but that returns with no output, because it thinks there's nothing new to fetch.

I tried unpacking .git/objects/pack/pack-ea43d1db155e4502c2250ec1d4608843715c8b1f.pack, several ways, but it never worked. For example:

% git clone --mirror git://github.com/strugee/dots.git # returns bare repo
Cloning into bare repository 'dots.git'...
remote: Counting objects: 1331, done.
remote: Compressing objects: 100% (23/23), done.
remote: Total 1331 (delta 12), reused 0 (delta 0)
Receiving objects: 100% (1331/1331), 402.31 KiB | 197.00 KiB/s, done.
Resolving deltas: 100% (454/454), done.
Checking connectivity... done.
% ls dots.git
config  description  HEAD  hooks  info  objects  packed-refs  refs
% mkdir git-tmp; cd git-tmp
% git init
% git unpack-objects < ../dots.git/objects/pack/pack-ea43d1db155e4502c2250ec1d4608843715c8b1f.pack
error: inflate: data stream error (incorrect data check)
error: inflate returned -3

I got this error every time. (Keep in mind: it's a --mirror, so it's an exact copy of what GitHub has - right? How could it be corrupt then?)

Eventually I realized that I didn't actually need to unpack the packfile. I could just copy it back into the original repo, and Git would pick it up just fine. So:

% cd ../configs
% cp ../dots.git/objects/pack/pack-ea43d1db155e4502c2250ec1d4608843715c8b1f.* .git/objects/pack/

And that seemed to do the trick. Mostly.

% git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (2596/2596), done.
broken link from  commit db238d4a52ee8f18a04c038809bc6587d7643438
              to    tree 0b69ab3f6940a04684ee8c0c423ae7da89de749c
dangling commit 05512f9ac09d932e7d9a11d490c8a2f117c0ca11
dangling commit 578464dde7d7b8628f77e536b4076cfa491d7602
missing blob 5d351b568abb734605ca4bf446e13cfd87ca9ce8
missing tree 0b69ab3f6940a04684ee8c0c423ae7da89de749c
dangling blob d53a9d0f3364b648edbc4beede022e4594a84c35
dangling commit 8dcbde55462ca0c29e0ca339a49db95b43188ef1
dangling commit 85fdaaa579cf1ae2a8874e3e1f3c65d68b478179
dangling commit 075e9d72e90cc8bf3d960edd8376aaae0847f916
missing blob 83fec2ff8cfcaaa06c96917b6973ace96301e932
dangling commit a88e18e1c102d909361738fd70137b3f4a1c7496
dangling commit ca9fe0dd3123a731fc310b2a2285b00ef673de79

As you can see, that repaired all but one missing link. As it turns out, db238d is the id of a commit (which happens to be HEAD^) that I had not yet pushed. Am I correct in assuming that the last two commits in this repository are unrecoverable, and I will need to recreate the contents of those commits? Did I make the right decisions in this scenario?

解决方案

Try git fetch-pack to recover missing objects available from another repository. Instructions below.

For recovery of unpushed commits, specifically HEAD^1 I would start with

git diff-tree -r HEAD~2^{tree} HEAD^{tree}

You'll get a list of all trees/blobs that have changed and their SHAs (which would include the changes from both HEAD and HEAD^1). Depending on how much information is available you may be able to recreate some of all of the missing tree. Missing blobs are more problematic though.

Use of git fetch-pack

Intentionally corrupt repository

me@myvm:/scratch/corrupt/.git  (GIT_DIR!)$ cd objects/
me@myvm:/scratch/corrupt/.git/objects  (GIT_DIR!)$ ll
total 20
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 20
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 22
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 25
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 info
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 pack
me@myvm:/scratch/corrupt/.git/objects  (GIT_DIR!)$ rm -rf 22

Verify head in bad state

me@myvm:/scratch/corrupt/.git/objects  (GIT_DIR!)$ cd ../../
me@myvm:/scratch/corrupt  (master)$ git status
fatal: bad object HEAD

recover missing objects

me@myvm:/scratch/corrupt  (master)$ git fetch-pack --all $(git config --get remote.origin.url)
error: refs/heads/master does not point to a valid object!
error: refs/remotes/origin/HEAD does not point to a valid object!
error: refs/remotes/origin/master does not point to a valid object!
error: refs/heads/master does not point to a valid object!
error: refs/remotes/origin/HEAD does not point to a valid object!
error: refs/remotes/origin/master does not point to a valid object!
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
22ecde746be79c65b27a5cf1dc421764d8ff6e17 HEAD
22ecde746be79c65b27a5cf1dc421764d8ff6e17 refs/heads/master
me@myvm:/scratch/corrupt  (master)$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

missing objects restored

me@myvm:/scratch/corrupt  (master)$ ll .git/objects/
total 20
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 20
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:05 22
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 25
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 info
drwxrwxr-x 2 andrewc warp 4096 Oct  7 06:03 pack
me@myvm:/scratch/corrupt  (master)$ 


me@myvm:/scratch/corrupt  (master)$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

If you end up in a state where you can find a broken tree object and a broken blob object you can manually recover those. You can git cat-file -p BLOB_SHA for any blob, this will dump the contents. If you can figure out by looking at the contents what the file is that can help you recover the file. Likewise git cat-file -p TREE_SHA will dump the tree, which tells you file names and blob SHAs. At this point you would be attempting to manually construct tree and commit objects from presumably partial data. If your HEAD commit is OK then you are only missing history and should at least have the most recent state covered.

这篇关于我怎样才能恢复HEAD ^'S树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆