紛らわしいビットはここにあります:
Gitはこれらを個別のファイルと見なしません。Gitはすべてを完全なコンテンツと見なします。
多くの場合、Gitは自身のリポジトリのオブジェクトの代わりに160ビットハッシュを使用します。ファイルのツリーは、基本的に、各コンテンツ(およびいくつかのメタデータ)に関連付けられた名前とハッシュのリストです。
しかし、160ビットのハッシュは(gitデータベースのユニバース内で)コンテンツを一意に識別します。したがって、コンテンツとしてハッシュを持つツリーには、その状態のコンテンツが含まれます。
ファイルのコンテンツの状態を変更すると、そのハッシュが変更されます。ただし、ハッシュが変更されると、ファイル名のコンテンツに関連付けられているハッシュも変更されます。これにより、「ディレクトリツリー」のハッシュが変更されます。
gitデータベースがディレクトリツリーを格納する場合、そのディレクトリツリーは、すべてのサブディレクトリとその中のすべてのファイルのすべてのコンテンツを意味し、含みます。
これは、ブロブまたは他のツリーへの(不変、再利用可能な)ポインターを持つツリー構造で編成されますが、論理的には、ツリー全体のコンテンツ全体の単一のスナップショットです。gitデータベースでの表現はフラットなデータ内容ではありませんが、論理的にはすべてのデータであり、それ以外のものではありません。
ツリーをファイルシステムにシリアル化し、すべての.gitフォルダーを削除し、gitにツリーをデータベースに戻すように指示した場合、データベースには何も追加されず、要素は既に存在します。
gitのハッシュを、不変データへの参照カウントされたポインタと考えると役立つ場合があります。
その周りにアプリケーションを作成した場合、ドキュメントはページの集まりであり、ページにはレイヤー、グループ、オブジェクトがあります。
オブジェクトを変更する場合は、そのオブジェクト用に完全に新しいグループを作成する必要があります。グループを変更する場合は、新しいページを必要とし、新しいドキュメントを必要とする新しいレイヤーを作成する必要があります。
1つのオブジェクトを変更するたびに、新しいドキュメントが生成されます。古いドキュメントは引き続き存在します。新旧のドキュメントは、ほとんどのコンテンツを共有します-それらは同じページです(1を除く)。その1つのページには同じレイヤーがあります(1を除く)。そのレイヤーには同じグループがあります(1を除く)。そのグループには同じオブジェクトがあります(1を除く)。
同様に、私は論理的にはコピーを意味しますが、実装に関しては、同じ不変オブジェクトへの参照カウントされた別のポインタにすぎません。
gitリポジトリはそのようなものです。
つまり、特定のgitチェンジセットにはコミットメッセージ(ハッシュコードとして)が含まれ、ワークツリーが含まれ、親の変更が含まれます。
これらの親の変更には、親の変更がすべて含まれます。
履歴を含むgitリポジトリの一部は、その一連の変更です。そのチェーンは、「ディレクトリ」ツリーの上のレベルで変更されます。「ディレクトリ」ツリーから、変更セットと変更のチェーンに一意に到達することはできません。
ファイルがどうなるかを調べるには、チェンジセット内のそのファイルから始めます。そのチェンジセットには歴史があります。多くの場合、その履歴では、同じ名前のファイルが存在し、内容が同じ場合もあります。内容が同じ場合、ファイルは変更されていません。それが異なる場合、変化があり、正確に何が起こるかを理解するために作業を行う必要があります。
時々、ファイルはなくなっています。しかし、「ディレクトリ」ツリーには同じコンテンツ(同じハッシュコード)を持つ別のファイルが含まれている可能性があるため、その方法で追跡できます(注:これは、commit-to-commitとは別にファイルを移動する必要がある理由です) -編集)。または、同じファイル名で、ファイルをチェックした後、十分に類似しています。
したがって、gitは「ファイル履歴」を一緒にパッチワークできます。
ただし、このファイル履歴は、「変更セット全体」を効率的に解析した結果であり、ファイルのバージョン間のリンクからのものではありません。