コンピューター科学者のための内部git



Git Internal Computer Scientists



http://eagain.net/articles/git-for-computer-scientists/

gitオブジェクトストレージは単なる オブジェクトには、いくつかの種類のオブジェクトがあります。それらはすべて圧縮されて保存され、SHA-1ハッシュでマークされます。

Blob:最も単純なオブジェクトは単なるバイトの山です。多くの場合、これは単なるファイルですが、シンボリックリンクなどの場合もあります。 BLOBのオブジェクトをポイントして、BLOBの特定のセマンティクスを指定します。



tree:ディレクトリはtreeオブジェクトでマークされています。これらは、ファイルコンテンツを含む関連するBLOBと、他のサブディレクトリを指すツリーを参照します。



ノードがDAG内の別のノードを指す場合、そのノードはポイントされたノードに依存します。つまり、このノードは、ポイントされたノードなしでは存在できません。他のノードがポイントしていないノードは、git gcコマンドによって回復されるか、ファイルシステムを指すファイル名がないinodes緊急レスキューコマンドのように復元されます。gitfsck--lost-found

commit:commitは、コミットが実行されたときのファイルセットの状態を反映するツリーオブジェクトを指します。また、0..nコミットをその親として引用します。複数の親コミットは、これがマージコミットであることを意味し、親のないコミットは、それが初期コミットであることを意味します。もちろん、複数の初期コミットが存在する場合があります。これは通常、2つの独立したプロジェクトがマージされることを意味します。コミットオブジェクトの内容はコミットメッセージです。



参照:参照、またはヘッドまたはブランチは、DAGのノード上の付箋のようなものです。ノードの追加のみを許可し、変更を許可しないDAGの機能とは異なり、このメモは任意に移動できます。それらは履歴に記録されず、レポ間で直接渡されることもありません。ブックマークのようなもので、「私はここで働いています」とアナウンスします。

git commitコマンドは、DAGにノードを追加し、メモを現在のブランチからこの新しいノードに移動します。

HEAD refは、実際には別のrefを指しているため、特別です。通常、現在アクティブなブランチを指します。一般的な参照は実際にはheads / xxxの名前空間にありますが、heads / partを無視する傾向があります

リモート参照:リモート参照は別の色でマークされています。これも付箋です。通常の参照との違いは名前空間が異なることです。実際、リモート参照は通常リモートサーバーによって制御され、gitフェッチ操作中に更新されます。

タグ:タグはDAGのノードであるだけでなく、付箋でもあります。タグはコミットを指し、オプションのメッセージとGPG署名が含まれています

付箋自体は、タグにアクセスするための簡単な方法を提供するだけです。失われると、git fsck--lost-foundを介して取得することもできます

DAG内のノードは、あるリポジトリから別のリポジトリに移動でき、より効率的な方法(パック)で保存でき、使用されなくなったノードはガベージクリーンアップされます。

しかし、結局のところ、gitリポジトリは常にDAGであり、対応するメモのコレクションです。

歴史:

gitがバージョン履歴を保存する方法に関する上記の知識がある場合、マージなどのアクションをどのように視覚化できますか?グラフィックを使用して表現するのが最善です。

上記は最も単純なリポジトリであり、リモートリポジトリのクローンを作成しましたが、リポジトリにはコミットが1つしかありません

上記でリモートをフェッチしましたが、フェッチには別の人のコミットが含まれており、コミットはマージされていません

上の図は、git merge remotes / myserver / masterを実行した後の状況を示しています。マージは早送りであるため(つまり、上海のローカルブランチに新しい変更がないため、直接早送りできます)、マージ後の唯一の変更は、メモを新しいノードに移動し、そしてそれに応じて作業ディレクトリの内容を変更しました

上の図では、ローカルコミットがあり、git fetchアクションを実行しました。引き続き、ローカルで新しいコミットと新しいリモートコミットがあります。この場合、マージが必要です。

git merge remotes / myserver / masterの実行結果は上記のとおりです。新しいローカルコミットがあるため、現時点では早送りではありませんが、DAGに新しいコミットノードを作成してマージを指示する必要があります。現時点では、マージコミットには2つの親コミットがあることに注意してください。

上の図では、いくつかの新しいコミットと新しいマージを行いました。 git DAGは、発生したアクションの履歴を記録します

上記の「ステッチ」パターンは、煩わしいように見える場合があります。ブランチをまだ公開していない場合、または他の人がブランチに基づいて作業するべきではないことを明確に伝えている場合は、別のオプションがあります。マージする代わりにブランチをリベースできます。これの利点は次のとおりです。コミットが次のようになります。別の親を持つ別のコミットがそれを置き換え、ブランチがそこに移動します。 (このコミットは、リモートブランチの最新のコミットを親コミットとして使用します)

古いコミットは、gitのガベージコレクションメカニズムが機能して削除するまで、DAGに保存されます。もちろん、古いコミットを指す余分な付箋がある場合、それらは常にそれを指します。誰かが未使用のコミットを指しているという理由だけで、これは古いコミットを保存し、ゴミによってクリーンアップされません。

他の人が新しいコミットを作成したブランチをリベースしないでください。

ガベージコレクション後の状況は上の図のようになり(またはわずかにまたはわずかに到達不能なコミット)、リベースされたブランチに新しいコミットが作成されます

リベースは、1つのコミットで複数のコミットをリベースする方法も知っています