web-dev-qa-db-ja.com

githash-objectがopensslsha1とは異なるハッシュを返すのはなぜですか?

コンテキスト: ファイル(Audirvana 0.7.1.Zip) code.googleからMacbookPro(Mac OS X 10.6.6)にダウンロードしました。

チェックサムを確認したかったのですが、その特定のファイルについては862456662a11e2f386ff0b24fdabcb4f6c1c446a(SHA-1)として投稿されています。 git hash-objectは私に別のハッシュを与えましたが、openssl sha1予期された862456662a11e2f386ff0b24fdabcb4f6c1c446aを返しました。

次の実験は、ダウンロードの破損や改行の違いの可能性を排除し、実際には2つの異なるアルゴリズムが機能していることを示しているようです。

$ echo A > foo.txt
$ cat foo.txt
A
$ git hash-object foo.txt 
f70f10e4db19068f79bc43844b49f3eece45c4e8
$ openssl sha1 foo.txt 
SHA1(foo.txt)= 7d157d7c000ae27db146575c08ce30df893d3a64

どうしたの?

48
twcamper

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
55
Mark Longair

SHA1ダイジェストは、ヘッダー文字列とそれに続くファイルデータに対して計算されます。ヘッダーは、オブジェクトタイプ、スペース、および10進数のバイト単位のオブジェクト長で構成されます。これは、ヌルバイトによってデータから分離されています。

そう:

$ git hash-object foo.txt
f70f10e4db19068f79bc43844b49f3eece45c4e8
$ ( Perl -e '$size = (-s shift); print "blob $size\x00"' foo.txt \
               && cat foo.txt ) | openssl sha1
f70f10e4db19068f79bc43844b49f3eece45c4e8

この結果の1つは、「the」空のツリーと「the」空のblobのIDが異なることです。あれは:

e69de29bb2d1d6434b8b29ae775ad8c2e48c5391は常に「空のファイル」を意味します4b825dc642cb6eb9a060e54bf8d69288fbee4904は常に「空のディレクトリ」を意味します

実際には、オブジェクトが登録されていない新しいgitリポジトリでgit ls-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904を実行できることがわかります。これは、特殊なケースとして認識され、実際に保存されることはないためです(最新のGitバージョンでは)。対照的に、空のファイルをリポジトリに追加すると、blob「e69de29bb2d1d6434b8b29ae775ad8c2e48c5391」が保存されます。

4
araqnid

答えはここにあります:

Git SHA1をGitなしのファイルに割り当てる方法は?

gitは、コンテンツだけでなく、ファイルのメタデータ+コンテンツを計算します。

今のところ、これで十分です。要点は、gitはダウンロードをチェックサムするためのツールではないということです。

2
twcamper