Dev Study
← 解説「ブランチの正体 — 40文字が書かれた41バイトのファイル」に戻る

サンプルコードで身につける: ブランチの正体 — 40文字が書かれた41バイトのファイル

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1ブランチファイルを直接見る

ブランチの実体が本当に41バイトのファイルであることを、ls と cat で確かめた実際の出力です。2つのブランチが同じコミットを指しているときは、中身の40文字も完全に同じになります。

$ git branch feature-login

# ブランチはただのファイル。サイズは41バイト(40文字 + 改行)
$ ls -l .git/refs/heads/
-rw-r--r--  41  feature-login
-rw-r--r--  41  main

$ cat .git/refs/heads/main
dd2818b6f87da96757d1cd70f43e293660aece49

$ cat .git/refs/heads/feature-login
dd2818b6f87da96757d1cd70f43e293660aece49

# HEADはブランチ名を指している(コミットではない)
$ cat .git/HEAD
ref: refs/heads/main

2ブランチ作成でオブジェクトは1つも増えない

ブランチを作る前後でオブジェクト数を数えた実際の出力です。41バイトのファイルが1つ増えるだけで、オブジェクトDBは全く変わりません。これが「ブランチ作成が一瞬で終わる」ことの正体です。

# ブランチを作る前
$ git rev-list --objects --all | wc -l
8

$ git branch feature-login

# 作った後 — 変わっていない
$ git rev-list --objects --all | wc -l
8

# 切り替えてもオブジェクトは増えない
$ git checkout feature-login
Switched to branch 'feature-login'
$ git rev-list --objects --all | wc -l
8

# 変わったのは HEAD の中身だけ
$ cat .git/HEAD
ref: refs/heads/feature-login

3checkoutで起きていることを分解する

ブランチ切り替えは「HEADの書き換え」と「作業ツリーの並べ直し」の2段階です。オブジェクトは既にDBにあるので、ダウンロードもコピーも起きません。その手順を擬似コードで追います。

Python

4コミットするとブランチが自動で進む理由

HEAD → ブランチ → コミットという二段構造なので、コミット時に書き換わるのは「HEADが指しているブランチファイル」だけです。手動でブランチを動かす必要がないのはこのためです。

Python

540文字を覚えなくてよくするのがブランチ

ブランチもタグも「人間が読める名前 → 40文字」の対応表にすぎません。名前が無くてもハッシュを直接指定すれば同じことができます。ブランチが特別な存在ではないと分かるサンプルです。

# ブランチ名で指定する(いつものやり方)
$ git show main --oneline -s
dd2818b READMEに使い方を追加

# 40文字を直接指定しても全く同じ
$ git show dd2818b6f87da96757d1cd70f43e293660aece49 --oneline -s
dd2818b READMEに使い方を追加

# 名前 → ハッシュ の対応はこれで一覧できる
$ git show-ref
dd2818b6f87da96757d1cd70f43e293660aece49 refs/heads/main
dd2818b6f87da96757d1cd70f43e293660aece49 refs/heads/feature-login

# 名前を解決した結果を確認する
$ git rev-parse main
dd2818b6f87da96757d1cd70f43e293660aece49