Git 如何恢复头部^';这棵树是什么?

Git 如何恢复头部^';这棵树是什么?,git,data-recovery,git-fsck,git-plumbing,Git,Data Recovery,Git Fsck,Git Plumbing,tl;dr:如果删除了头^的树,而不是事先推送,并且其他所有内容都完好无损,是否可以恢复该树 我不小心删除了我的.git的一部分。我不完全确定遗漏了什么 当发现git-push不起作用时,我运行了一个git-fsck: Checking object directories: 100% (256/256), done. Checking objects: 100% (1265/1265), done. broken link from commit f3419f630546ba02baf43f

tl;dr:如果删除了
头^
的树,而不是事先推送,并且其他所有内容都完好无损,是否可以恢复该树

我不小心删除了我的
.git
的一部分。我不完全确定遗漏了什么

当发现
git-push
不起作用时,我运行了一个
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
所以我的假设是,我只是缺少一些可以从GitHub中恢复的信息。我下意识的反应是运行
git fetch
,但它返回时没有输出,因为它认为没有什么新的东西可以获取

我尝试了几种方法来解包
.git/objects/pack/pack-ea43d1db155e4502c250ec1d4608843715c8b1f.pack
,但都没有成功。例如:

% 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
这似乎起到了作用。大部分

% 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
正如你所见,这修复了除了一个缺失的链接以外的所有链接。事实证明,
db238d
是我尚未推送的提交的id(恰好是
HEAD^
)。假设此存储库中的最后两次提交是不可恢复的,并且我需要重新创建这些提交的内容,这是否正确?在这种情况下,我是否做出了正确的决定?

尝试从另一个存储库中恢复丢失的可用对象。说明如下

对于恢复未推送的提交,特别是头^1,我将从

git diff-tree -r HEAD~2^{tree} HEAD^{tree}
您将获得所有已更改的树/斑点及其SHA的列表(其中包括HEAD和HEAD ^1的更改)。根据可用信息的多少,您可以重新创建丢失的部分树。不过,丢失的斑点问题更大

使用
git获取包

故意损坏存储库

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
确认磁头处于不良状态

me@myvm:/scratch/corrupt/.git/objects  (GIT_DIR!)$ cd ../../
me@myvm:/scratch/corrupt  (master)$ git status
fatal: bad object HEAD
恢复丢失的对象

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
已恢复丢失的对象

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
如果您最终处于一种可以找到一个断开的树对象和一个断开的blob对象的状态,那么您可以手动恢复它们。您可以
git cat file-p BLOB_SHA
为任何BLOB转储内容。如果您可以通过查看内容来确定文件是什么,则可以帮助您恢复文件。同样地,
git cat file-p TREE_SHA
将转储该树,它告诉您文件名和blob SHA。此时,您将尝试手动构造树并从假定的部分数据提交对象。如果您的HEAD commit没有问题,那么您只缺少历史记录,至少应该覆盖最近的状态

所以我的假设是,我只是缺少一些可以从GitHub中恢复的信息

一般来说是正确的,但如果您能够准确地识别断开的链接来自何处,则会有所帮助

这就是Git 2.10(2016年第3季度)的提议,其中包括:

参见,,(2016年7月17日)作者。
(于2016年7月25日被合并)

fsck
:可选显示断开链接的更多有用信息 当“
git fsck
”报告断开的链接(例如,树对象包含不存在的blob)时,包含对象和引用的对象都报告有其40个十六进制对象名称。
命令学习了“
--name objects
”选项,以显示从现有引用到包含对象的路径(例如“
HEAD~24^2:file.txt
”)


三年后,git fsck正在git 2.25(2020年第1季度)中进行重构:“git fsck”中使用的对象解析和低级对象访问过程中积累的粗糙代码和逻辑已经清理干净

这反过来又修复了fsck如何装饰其条目

参见,,,,,(2019年10月18日)和(2019年10月25日)的作者。
(于2019年12月1日合并)

:统一对象名称代码 签字人:杰夫·金

提交(“
fsck
:可选显示断开链接的更多有用信息”,2016-07-17,Git v2.10.0-rc0——中列出)添加了一个用名称装饰对象的系统。代码分为(给出初始名称)和(在遍历对象图时添加名称)。
这导致了一些重复,两个站点都有几乎相同的
descripe\u object()
函数(不同之处在于,中的一个站点使用循环缓冲区数组,允许在单个
printf
中进行多个调用)

让我们为
fsck
提供一个统一的
object\u name
API

这使我们能够消除重复,并使接口边界更加清晰(这将使我们在未来的补丁中更加重构实现)

我们将把
description_object()
作为新API的薄包装留在中,因为它依赖于一个静态全局函数来缩短其许多调用者

我们还将把裸
add_decoration()
调用转换为
put_object_name()

这修复了两个小错误:

  • 我们漏了很多细绳。add_decoration()有一种“最后一个赢”的方法:它将装饰更新为新字符串并返回旧字符串。但是我们忽略了返回值,泄漏了旧字符串。
    这是很常见的触发方式,因为我们查看reflogs:任何ref的提示都将通过查看实际ref以及最新的reflog条目来描述。
    所以我们总是会漏掉其中一根弦

  • 最后一个胜出的方法给了我们糟糕的名字。
    例如,我们首先查看所有参考,然后再查看所有回流。
    因此,与其看到“
    refs/heads/master
    ”,我们可能会用“
    HEAD@{12345678}
    ”覆盖它 我们通常最好使用我们找到的名字

  • 实际上,t1450中的测试需要这个丑陋的
    HEAD@{}
    name.
    在这个补丁之后,我们切换到使用
    fsck\u put\u object\u name()
    的第一个wins语义,并且我们输出了更多的人类fri
    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
    
    git fsck --name-objects