1. ホーム
  2. git

[解決済み] git の半秘密の空のツリーオブジェクトは信頼できますか?なぜシンボル名がないのですか?

2022-06-06 22:35:13

質問

Gitには、よく知られた、あるいは少なくともある種のよく知られた、SHA1が空のツリーがあります。

4b825dc642cb6eb9a060e54bf8d69288fbee4904

(これはどのレポでも、新しく作ったレポでも git cat-file -tgit cat-file -p ). [ 2020年に行われた編集 : SHA-256空木ハッシュIDは。

6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321

として VonCが回答で触れている . 私の質問は約8年早かったようです。????]

もしあなたが一生懸命に、そして非常に注意深く作業するならば、この空のツリーを、ファイルのないディレクトリを保存するために使うことができます(参照 空のディレクトリを git リポジトリに追加するにはどうすればよいですか? を参照)、あまり良いアイデアではありませんが。

の一つの引数としてより有用です。 git diff-tree の1つの引数として、より有用です。

私が疑問に思っているのは

  1. これはどの程度信頼できるのでしょうか。つまり、将来のバージョンの git には git オブジェクト番号がないのでしょうか。 4b825dc642cb6eb9a060e54bf8d69288fbee4904 ?
  2. なぜ空のツリーにはシンボル名がないのでしょうか(あるのでしょうか)。

(シンボル名を作成する手っ取り早い方法は、SHA1を入れることです、例, .git/Nulltree . 残念ながら、あなたはすべてのレポについてこれをしなければなりません。 スクリプトなどにマジックナンバーを入れる方がよさそうです。 私はマジックナンバーに一般的な嫌悪感を抱いているだけです)。

どのように解決するのですか?

このスレッド が言及しています。

空木のsha1を覚えていない場合は、常にで導出することができます。

git hash-object -t tree /dev/null

または、次のように チロ・サンティリ プロポーズ コメントで :

printf '' | git hash-object --stdin -t tree

または、次のように ここに見られる から Colin Schimmelfing :

git hash-object -t tree --stdin < /dev/null

というわけで、(よく知られた値に頼るのではなく)そのコマンドの結果を空のsha1ツリーとして変数に定義するのが安全だと思います。

注:Git 2.25.1 (Feb. 2020)では、Git 2.25.1 で提案された コミット 9c8a294 :

empty_tree=$(git mktree </dev/null)
# Windows:
git mktree <NUL

と追加します。

歴史的なメモとして、現在では repo_read_object_file() で空のツリーを教えていました。 346245a1bb ("hard-code the empty tree object", 2008-02-13, Git v1.5.5-rc0 --) で教えてもらいました。 マージ として知られている関数です)。 oid_object_info() で空のツリーを教えていました。 c4d9986f5f (" sha1_object_info 調べる cached_object store too", 2011-02-07, Git v1.7.4.1)。


なお、GitHub のリポジトリで SHA1 が表示されるのは、作者が最初のコミットを空にしたい場合です (ブログ記事 " を参照)。 Git リポジトリを初期化する方法 を参照)。

$ GIT_AUTHOR_DATE="Thu, 01 Jan 1970 00:00:00 +0000" GIT_COMMITTER_DATE="Thu, 01 Jan 1970 00:00:00 +0000" git commit --allow-empty -m 'Initial commit'

を与えるだろう。

(ツリーのSHA1を見てください)

その空のコミットの上に、既存の履歴をリベースすることもできます(" git: あるコミットを最初のコミットとして挿入し、他のコミットをすべてシフトするには? をご覧ください)。

どちらの場合も、その空のツリーの正確なSHA1値には依存しないのですね。

あなたは単に ベストプラクティスに従うだけで、最初の空のコミットでレポを初期化します。 .


そのためには

git init my_new_repo
cd my_new_repo
git config user.name username
git config user.email email@com

git commit --allow-empty -m "initial empty commit"

これにより、あなたのレポ、ユーザー名、メールアドレス、作成日に固有のSHA1を持つコミットが生成されます(つまり、コミット自体のSHA1は毎回異なるということです)。

しかし、そのコミットによって参照されるツリーは 4b825dc642cb6eb9a060e54bf8d69288fbee4904 となり、空のツリーSHA1となります。

git log --pretty=raw

commit 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904      <====
author VonC <[email protected]> 1381232247 +0200
committer VonC <[email protected]> 1381232247 +0200

    initial empty commit

コミットのツリーだけを表示する(コミットツリーのSHA1を表示する)。

git show --pretty=format:%T 9ed4ff9ac204f20f826ddacc3f85ef7186d6cc14
4b825dc642cb6eb9a060e54bf8d69288fbee4904

もし、空のツリーを参照しているそのコミットが、本当にあなたの 最初の のコミットであれば、その空のツリーの SHA1 を表示することができます。

git log --pretty=format:%h --reverse | head -1 | xargs git show --pretty=format:%T
4b825dc642cb6eb9a060e54bf8d69288fbee4904

(これは Windows でさえ WindowsのGnu コマンドで動作します)。


として のコメント を使用すると git diff <commit> HEAD を使うと、現在のブランチのHEADにあるすべてのファイルが表示されます。

git diff --name-only 4b825dc642cb6eb9a060e54bf8d69288fbee4904 HEAD


注意: 空のツリー値は、正式には cache.h .

#define EMPTY_TREE_SHA1_HEX \
    "4b825dc642cb6eb9a060e54bf8d69288fbee4904"

Git 2.16(2018年第1四半期)以降、以下のように(SHA1だけに)縛られない構造で使用されるようになりました。 コミット eb0ccfd :

<ブロッククオート

空のツリーと blob の検索をハッシュの抽象化を使用するように切り替え

の使用方法を変更 empty_tree_oidempty_blob_oid を使用することで current_hash 抽象化され、現在使用されているハッシュアルゴリズムが表示されます。 を使用します。

詳しくは"でご覧ください。 なぜGitはもっと現代的なSHAを使わないのですか? ": そうです。 SHA-2 , Git 2.19(2018年第3四半期)以降。


Git 2.25 (2020 年第 1 四半期) で、テストが準備されています。 SHA-2 への移行 を準備中で、空のツリーを巻き込んでいます。

参照 コミット fa26d5e , コミット cf02be8 , コミット 38ee26b , コミット 37ab8eb , コミット 0370b35 , コミット 0253e12 , コミット 45e2ef2 , コミット 79b0edc , コミット 840624f , コミット 32a6707 , コミット 440bf91 , コミット 0b408ca , コミット 2eabd38 (2019年10月28日)、および コミット 1bcef51 , コミット ecde49b (2019年10月05日)によって ブライアン・M・カールソン ( bk2204 ) .

(によって統合されました。 ジュニオ・C・ハマノ--。 gitster -- コミット 28014c1 , 2019年11月10日)

t/oid-info : 空のツリーと空のブロブ値を追加

署名: Brian M. Carlson

テストスイートはいずれ、SHA-1以外のアルゴリズムを使って実行する方法を学習します。この準備のために test_oid 関数のファミリーに、空のブロブと空のツリーの値を調べる方法を教えて、それらが使えるようにします。

では t/oid-info/hash-info が含まれるようになりました。

rawsz sha1:20
rawsz sha256:32

hexsz sha1:40
hexsz sha256:64

zero sha1:0000000000000000000000000000000000000000
zero sha256:0000000000000000000000000000000000000000000000000000000000000000

algo sha1:sha1
algo sha256:sha256

empty_blob sha1:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
empty_blob sha256:473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813

empty_tree sha1:4b825dc642cb6eb9a060e54bf8d69288fbee4904
empty_tree sha256:6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321

SHA2の"です。 6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321 "は、新しいSHA1 "です。 4b825dc642cb6eb9a060e54bf8d69288fbee4904 "空のツリーです。