初級編では、Gitを「コードのためのタイムマシン」として、その基本的な使い方を学びましたね。add
, commit
, push
... これらのコマンドが、君のコードの歴史を記録してくれる便利な呪文であることはもう理解しているはずです。
この章では、一歩進んでそのタイムマシンのボンネットを開け、内部の仕組み、つまりGitの心臓部がどう動いているのかを探検します。ここを理解すると、「なぜブランチの作成は一瞬で終わるのか?」「マージとリベースは何が違うのか?」といった疑問が氷解し、Gitをより自在に、そして安全に操れるようになります。
.git
ディレクトリの中に - Gitの脳内探訪</h2>君が git init
や git clone
を実行したとき、プロジェクトのフォルダ内に .git
という名前の隠しディレクトリが作られていることに気づいていますか?実は、Gitの魔法のすべてがこの中に詰まっています。
.git
ディレクトリは、プロジェクトのフライトレコーダーや脳のようなものです。これまでの全歴史、誰が、いつ、何を変更したのか、そのすべてがこの中に記録されています。逆に言えば、このディレクトリさえあれば、プロジェクトのどんな過去の状態も復元できるのです。(だから、面白半分でこの中身を消したりは絶対にしないでくださいね!)
この中にはいくつかの重要なファイルやディレクトリがありますが、特に以下の3つがGitの心臓部を理解する鍵となります。
objects
ディレクトリ - データの本体が眠る場所</h3>ここには、君がGitに預けたすべてのデータが格納されています。ただし、ファイルがそのまま保存されているわけではありません。Gitはデータをオブジェクトという独自の形式に圧縮・変換して保存します。オブジェクトには主に3つの種類があります。これについては次のセクションで詳しく見ていきましょう。
refs
ディレクトリ - コミットを指し示す付箋置き場</h3>refs
は "references"(参照)の略です。ここには、ブランチやタグといった「目印」が保管されています。例えば、main
ブランチが今どのコミットを指しているか、といった情報がファイルとして記録されています。つまり、ブランチとは、特定のコミ-ットを指し示す、ただの**軽量なポインタ(付箋)**なのです。
HEAD
ファイル - 「君は今ここにいる」を示す矢印</h3>HEAD
は、君が今作業している場所を示す、極めて重要な特別なポインタです。通常、HEAD
は特定のブランチ(例:refs/heads/main
)を指しています。君が git checkout
でブランチを切り替えるとき、実際にはこの HEAD
が指し示す先を変更しているだけなのです。
git commit
を実行したとき、Gitの内部では一体何が起きているのでしょうか?Gitは変更を「差分」ではなく、スナップショットとして記録します。そしてそのスナップショットは、以下の3種類のオブジェクトの組み合わせで表現されます。
Blob (Binary Large Object) は、ファイルの中身だけを純粋に保存したものです。ファイル名やタイムスタンプといったメタ情報は一切含みません。Gitはファイルの中身が同じであれば、たとえファイル名が違っても、同じBlobオブジェクトを再利用します。これがGitの効率性の秘密の一つです。