git fsck --full只检查目录

时间:2017-01-07 11:52:46

标签: git

我从我的覆盆子pi中提供裸git回购。我的目标是每晚运行git fsck --full以尽早检测文件系统问题。我希望fsck检查"对象目录"和"对象",以及查看输出,如

pi@raspi2:/media/usb/git/dw.git $ git fsck --full
Checking object directories: 100% (256/256), done.
Checking objects: 100% (14538/14538), done.

对于我的一个仓库,没有检查任何对象:

pi@raspi2:/media/usb/git/ts-ch.git.borken $ git --version
git version 2.11.0
pi@raspi2:/media/usb/git/ts-ch.git.borken $ git fsck --full
Checking object directories: 100% (256/256), done.
pi@raspi2:/media/usb/git/ts-ch.git.borken $ 

我在/ objects下修改了一个文件(一个322kB .pdf文件)并再次运行fsck。它显示与以前相同的消息,没有错误。

cd objects/86/
chmod u+w f3e6e674431ab3006cbb56fddecbdb4a7724b4 
echo "foosel" >> f3e6e674431ab3006cbb56fddecbdb4a7724b4 
chmod u-w f3e6e674431ab3006cbb56fddecbdb4a7724b4 

所有回购都是相同的,它们是裸的,没有特殊的配置:

pi@raspi2:/media/usb/git/ts-ch.git $ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=true

我错过了什么吗?为什么未检测到此修改对象?它的SHA1肯定不再匹配了。谢谢你的任何提示!

2 个答案:

答案 0 :(得分:4)

关于腐败问题

是的,你错过了一些东西。也就是说,你没有以Git关注的方式破坏文件。存储在磁盘上的对象通常以对象类型开头,后跟空格,后跟大小(使用ASCII编号),后跟一个NUL。大小表明对象的大小,以及Git最终阅读的全部内容。因此,将数据添加到最终,就像实际上不会破坏对象一样。如果您用其他内容替换了文件的内容,那么您就会看到问题。

作为参考,对象格式详细信息位于Git User's Manual

  

对象存储格式

     

所有对象都有静态确定的"类型"它标识的格式   对象(即如何使用它,以及它如何引用其他对象)。那里   目前有四种不同的对象类型:" blob"," tree"," commit"和" tag"。

     

无论对象类型如何,所有对象都具有以下特征:它们   都用zlib放气,并且有一个不仅指定它们的标题   type,但也提供有关对象中数据的大小信息。它的   值得注意的是,用于命名对象的SHA-1哈希是哈希值   原始数据加上此标头,因此sha1sum 文件与对象不匹配   文件名。

     

因此,始终可以测试对象的一般一致性   独立于对象的内容或类型:所有对象都可以   通过验证(a)它们的哈希值与文件的内容相匹配来验证   (b)对象成功膨胀为形成序列的字节流   <ascii type without space> + <space> + <ascii decimal size> + <byte\0> + <binary object data>

     

结构化对象可以进一步具有其结构和连接性   其他对象已验证。这通常使用git fsck程序完成   生成所有对象的完整依赖关系图,并验证其内部   一致性(除了通过验证其表面的一致性   哈希)。

然而,有一个有趣的互动让我认为git fsck应该更加努力,并注意文件最后是否有垃圾。如果您尝试在该回购邮件上运行git gc,那么您最终会看到如下错误:

:: git gc
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
error: garbage at end of loose object '45b983be36b73c0788dc9cbcb76cbb80fc7bb057'
fatal: loose object 45b983be36b73c0788dc9cbcb76cbb80fc7bb057 (stored in .git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057) is corrupt
error: failed to run repack

似乎git gc实际上无法运行,git fsck应该抓住这个问题。

关于你为什么看不到&#34;检查对象&#34;

这个问题实际上非常简单:没有要检查的打包对象。那些住在.git/objects/pack。如果您没有任何这些文件,那么您将无法看到&#34;正在检查对象&#34;位。

答案 1 :(得分:0)

  
    

我仍然不明白为什么git拒绝报告它正在检查此仓库中的对象,

  
     

我不打算把它拿出来,因为我认为git fsck应该彻底检查所有操作应该有效

这可能与Git 2.12(2017年第一季度)附带的那两套补丁有关:在你的覆盆子pi上重新编译git 2.12可能会产生更好的结果。

见下文:建议使用Git 2.20(Q8 2018)。

  

&#34; git fsck&#34;现在更仔细地检查松散的物体。

commit cce044d点击commit c68b489commit f6371f9commit 118e6cecommit 771e7d5commit 0b20f1aJeff King (peff)(2017年1月13日) 。
Junio C Hamano -- gitster --于2017年1月31日commit 42ace93合并)

并且:

  

&#34; git fsck --connectivity-check&#34;根本没用。

请参阅commit a2b2285commit 97ca7ca(2017年1月26日),commit c20d4d7(2017年1月24日),commit c2d17b3commit c3271a0commit c6c7b16commit b4584e4commit 1ada11e(2017年1月16日)和commit 3e3f8bd(2017年1月17日)Jeff King (peff)
Junio C Hamano -- gitster --于2017年1月31日commit 4ba6197合并)

2018年11月更新:上面推荐的Git 2.12实际上引入了回归,这使得&#34; git fsck&#34;在处理截断的松散对象时陷入无限循环。

commit 98f425bcommit ccdc481commit 5632bafJeff King (peff)(2018年10月30日)。 (由Junio C Hamano -- gitster --合并于commit 879a8d4,2018年11月13日)

  

check_stream_sha1():处理输入下溢

     

此提交在fscking较大时修复了无限循环   截断的松散物体。

     

check_stream_sha1()函数使用mmap一个松散的对象缓冲区,一次输出4k输出,检查其sha1。
  当我们输出足够的字节(我们知道对象标题的大小),或zlib告诉我们除Z_OKZ_BUF_ERROR之外的任何内容时,循环退出。

     

后者是预期的,因为zlib可能会在我们的4k缓冲区中耗尽空间,这就是它告诉我们处理输出并再次循环的方式。

     

Z_BUF_ERROR也涵盖了另一种情况:zlib无法前进,因为它需要更多输入

     

这应该永远不会发生在这个循环中,因为虽然我们要对输出进行流式传输,但我们在mmap缓冲区中提供了整个缩小的输入。但是既然我们不检查这种情况,如果我们确实看到了,我们就会无限循环   截断的对象,认为zlib要求更多的输出空间。

Git 2.22(2019年第二季度)改进了#34; git fsck --connectivity-only&#34;,它确实省略了将任何无法从任何refs到达的对象筛选到无法到达和悬空所需的计算。
现在,在请求悬空对象时启用此功能(默认情况下已完成,但可以使用&#34; --no-dangling&#34;选项覆盖。)

commit 8d8c2a5commit df805edJeff King (peff)(2019年3月5日) (由Junio C Hamano -- gitster --合并于commit ea32776,2019年3月20日)

  

fsck:始终为无法到达的对象计算USED标志

     

--connectivity-only选项可以避免打开每个对象,而是打开   只标记带有标志的可到达对象,并将其与集合进行比较   所有对象。在3e3f8bd中更详细地讨论了该策略   (fsck:为--connectivity-check,2017-01-17)准备虚拟对象。

     

这意味着我们将每个无法访问的对象报告为悬空   在一个完整的fsck中,我们实际上已经打开并解析了每个无法访问的对象,用USED标志标记其子对象,意味着&#34;这是另一个对象提到的。#34; >   因此,我们只能将对象图中无法到达的段的尖端报告为悬空。

     

你可以通过一个简单的例子来看到这种差异:

tree=$(git hash-object -t tree -w /dev/null)
one=$(echo one | git commit-tree $tree)
two=$(echo two | git commit-tree -p $one $tree)
     

运行git fsck只会报告$ 2悬空,但使用--connectivity-only时,会报告两次提交(和树)。同样,使用--lost-found会写出所有三个对象。

     

我们可以让--connectivity-only像普通情况一样工作   单独传递无法访问的对象,解析它们并标记   他们称之为USED的对象。这仍然可以避免解析任何blob,   虽然我们支付访问任何无法访问的提交和树的成本   (可能会或可能不会明显,取决于你有多少)。