上下文:我从code.google 下载了一个文件(Audirvana 0.7.1.zip)到我的Macbook Pro(Mac OS X 10.6.6).
我想验证校验和,该特定文件的校验和发布为862456662a11e2f386ff0b24fdabcb4f6c1c446a(SHA-1).  git hash-object给了我一个不同的哈希,但openssl sha1返回了预期的862456662a11e2f386ff0b24fdabcb4f6c1c446a.
以下实验似乎排除了任何可能的下载损坏或换行差异,并表明实际上有两种不同的算法在起作用:
$ echo A > foo.txt
$ cat foo.txt
A
$ git hash-object foo.txt 
f70f10e4db19068f79bc43844b49f3eece45c4e8
$ openssl sha1 foo.txt 
SHA1(foo.txt)= 7d157d7c000ae27db146575c08ce30df893d3a64
这是怎么回事?
Mar*_*air 58
您会看到一个区别,因为git hash-object它不仅仅是对文件中的字节进行哈希处理 - 它在字符串"blob"之后加上文件大小,并在散列之前将NUL添加到文件的内容中.Stack Overflow的另一个答案中有更多细节:
或者,为了说服自己,尝试以下方法:
$ echo -n hello | git hash-object --stdin
b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0
$ printf 'blob 5\0hello' > test.txt
$ openssl sha1 test.txt
SHA1(test.txt)= b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0
SHA1 摘要是通过后跟文件数据的标头字符串计算得出的。标头由对象类型、空格和以字节为单位的十进制对象长度组成。这通过空字节与数据分开。
所以:
$ git hash-object foo.txt
f70f10e4db19068f79bc43844b49f3eece45c4e8
$ ( perl -e '$size = (-s shift); print "blob $size\x00"' foo.txt \
               && cat foo.txt ) | openssl sha1
f70f10e4db19068f79bc43844b49f3eece45c4e8
这样做的一个后果是“该”空树和“该”空 blob 具有不同的 ID。那是:
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 始终表示“空文件” 4b825dc642cb6eb9a060e54bf8d69288fbee4904 始终表示“空目录”
你会发现你实际上可以git ls-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904在一个没有注册对象的新 git 存储库中做,因为它被认为是一种特殊情况并且从未实际存储(使用现代 Git 版本)。相比之下,如果您向存储库添加一个空文件,则会存储一个 blob“e69de29bb2d1d6434b8b29ae775ad8c2e48c5391”。