在git diff时突然出现broken ling miss blob的情况,不明就理,网上goolge也下参考链接How to fix a broken repository
我的问题是文中说的A情况 have a “broken link” message
就是类似如下情况,参考文中它是直接移除文件来模拟这个情况:
$ mv .git/objects/4b/9458b3786228369c63936db65827de3cc06200 ../
$ git fsck –full
broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
to blob 4b9458b3786228369c63936db65827de3cc06200
missing blob 4b9458b3786228369c63936db65827de3cc06200
也就是说这个问题其实是你的.git/objects/xx/xxxxx丢失引起的.要想恢复主要就是重建这个丢失的文件.
git相关知识的理解
-
1.2 那么这个文件在哪里?
- 这个丢失的blob file(比如上面的4b9458b3786228369c63936db65827de3cc06200)文件,就保存在.git/objects/4b/…. 前两个字母是文件夹,后面的字母就是文件名了 1.2 这个文件到底是什么,怎么产生的?
-
就我这个git门外汉来说,它就是一个HASH值,git 好像是在每一个commit版本中对修改过的文件都自动生成一个对应的hash值来标识这个文件有更改,不同commit间只要对比这个值就可以知道文件是否有修改了.
(简单理解就是不同的hash值表示文件内容有差异,如果hash值一样,说明文件是相同的.所以如果你要生成对应的hash值,你就要确保不同版本的文件内容是相同的,这在后面恢复时会用的)
它也可以你自己手动生成,命令如下,这个在我们恢复时需要用到.git hash-object -w file
回到我们的问题,如何解决 miss blob file
知道了这个问题的原因就是丢失了一个关于hash的blob文件,那我们只要把它找回来就行了.怎么找回来?从任何你能得到该文件的地方COPY过来都行(可以从备份的git respo中,也可以从远程git respo中),只要文件名与miss blob的名字一致的就是了.如果都没有,那只能自己生成一个了.
- 2.1 如何查看是哪个文件的hash值?
-
使用
git ls-tree commit
查询,比如查询当前版本的所有文件的blob文件可以如下:anzyelay@ubuntu:PZJBY11$ git ls-tree HEAD 100644 blob 16b4ee58786b1c31dc05f495d4ebe7fe2a215a88 .gitignore 100644 blob 0fb0518faec22fdb5d1868265b5871e059a1ffc9 CUart.cpp 100644 blob ce33a837e98893be1251c532692bf13e604c5c77 CUart.h ... 100644 blob bd82f5bd464deacbba8fdc9b80ebdf0b550bca20 src.qrc anzyelay@ubuntu:PZJBY11$
上面通过
git fsck
可以知道是哪个版本的blob丢失,在寻找对应文件,直接引用参考文档里的内容了.$ git fsck –full
broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
to blob 4b9458b3786228369c63936db65827de3cc06200
missing blob 4b9458b3786228369c63936db65827de3cc06200$ git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8 .gitignore
100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883 .mailmap
100644 blob 4b9458b3786228369c63936db65827de3cc06200 my-error-file
100644 blob ee909f2cc49e54f0799a4739d24c4cb9151ae453 CREDITS
040000 tree 0f5f709c17ad89e72bdbbef6ea221c69807009f6 Documentation
100644 blob 1570d248ad9237e4fa6e4d079336b9da62d9ba32 Kbuild
100644 blob 1c7c229a092665b11cd46a25dbd40feeb31661d9 MAINTAINERS由上找到了blob对应的文件是my-error-file
- 2.2 知道了文件,那就要还原当时的文件内容,这样才能生成对应的hash值
-
如果你的丢失的blob的hash值对应的文件正好是你当前的文件,那恭喜你,直接
anzyelay@ubuntu:PZJBY11$ git hash-object -w my-error-file 9808b564a15c38833f2b13aee1ff36e302e22e34
看看生成的9808b564a15c38833f2b13aee1ff36e302e22e34这个数字是不是你要找的,如果不是,那你就是想办法还原my-error-file到对应的版本,在生成了.
悲剧的是我的就不是,只能找是哪个版本了,使用如下命令:git log --raw --all --full-history -- my-error-file commit abc Author: Date: ... :100644 100644 4b9458b... newsha... M my-error-file commit xyz Author: Date: ... :100644 100644 oldsha... 4b9458b... M my-error-file
这个命令可以查看不同commit下,对应文件的hash值变化过程,发现my-error-file的4b9458b是在 commit xyz时生成的,在commit abc后更改了内容所以hash值也变了.那就努力的还原到commit xyz版本时 my-error-file的内容吧,如果还原OK了,就在
git hash-object -w my-error-file
下,如果出来的结果是丢失的blob的值,那就恭喜你成功了,这时在git fsck下看看.