GitコミットIDは、コミットを一意に識別するためにどのように生成されますか?
例:521747298a3790fde1710f3aa2d03b55020575aa
どのように機能しますか?それらは各プロジェクトでのみ一意ですか?または、世界中のGitリポジトリの場合?
GitコミットIDは、コミットに関するすべての重要なものの SHA-1ハッシュ です。それらをすべてリストするつもりはありませんが、ここに重要なものがあります...
そのいずれかを変更すると、コミットIDが変更されます。そして、はい、同じプロパティを持つ同じコミットは、異なるマシン上で同じIDを持ちます。これには3つの目的があります。まず、コミットが改ざんされているかどうかをシステムが判断できることを意味します。アーキテクチャに直接組み込まれています。
第二に、IDを見るだけでコミットを迅速に比較できます。これにより、Gitのネットワークプロトコルは非常に効率的になります。 2つのコミットを比較して、それらが同じかどうかを確認したいですか?差分全体を送信する必要はなく、IDを送信するだけです。
第三に、これは天才です。同じIDを持つ2つのコミットは同じ履歴を持ちます。これが、以前のコミットのIDがハッシュの一部である理由です。コミットの内容が同じで、親が異なる場合、コミットIDは異なる必要があります。つまり、リポジトリを比較するとき(プッシュやプルなど)、Gitが2つのリポジトリ間で共通のコミットを見つけると、チェックを停止できます。これにより、プッシュとプルが非常に効率的になります。例えば...
Origin
A - B - C - D - E [master]
A - B [Origin/master]
git fetch Origin
のネットワーク会話は次のようになります...
local
ちょっとオリジン、あなたはどんなブランチを持っていますか?Origin
私はEにマスターがいます.local
私にはEがなく、Bにあなたのマスターがいます。Origin
Bあなたが言う?私にはBがあり、それはEの祖先です。 C、D、Eをお送りします。これが、rebaseでコミットを書き換えた場合、それ以降はすべて変更する必要があるためです。以下に例を示します。
A - B - C - D - E - F - G [master]
ログメッセージを少し変更するために、Dを書き換えたとします。これでDはDでなくなるため、D1を呼び出す新しいコミットにコピーする必要があります。
A - B - C - D - E - F - G [master]
\
D1
D1はCを親として持つことができますが(Cは影響を受けず、コミットは子を認識しません)、E、F、Gから切断されます。Eの親をD1に変更すると、EはEになりません。新しいコミットE1にコピーする必要があります。
A - B - C - D - E - F - G [master]
\
D1 - E1
FからF1、GからG1のように続きます。
A - B - C - D - E - F - G
\
D1 - E1 - F1 - G1 [master]
それらはすべて同じコードを持ち、異なる親(またはD1の場合は異なるコミットメッセージ)だけを持ちます。
実行することにより、コミットIDの作成に何が入るかを正確に確認できます。
git cat-file commit HEAD
それはあなたに何かを与えるでしょう
tree 07e239f2f3d8adc12566eaf66e0ad670f36202b5
parent 543a4849f7201da7bed297b279b7b1e9a086a255
author Justin Howard <[email protected]> 1426631449 -0700
committer Justin Howard <[email protected]> 1426631471 -0700
My commit message
それはあなたに与えます:
Gitはこれをすべて実行し、sha1ハッシュを実行します。実行することでコミットIDを再現できます
(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum
これは、文字列commit
の後にスペースとcat-file
テキストブロブのバイトカウントが続くことから始まります。次に、cat-file
blobを追加し、その後にヌルバイトを追加します。これらはすべてsha1sum
を介して実行されます。
ご覧のとおり、この情報にはプロジェクトまたはリポジトリを識別するものは何もありません。これが問題を引き起こさない理由は、2つの異なるコミットハッシュが衝突する可能性が天文学的に低いためです。