GIT VISUALIZER

git commit

git commit を実行したとき、内部で何が起きているかを可視化します。

初期状態
git commit 実行前の状態(git add 済み)
git add が完了し、3つの blob と index エントリが準備されています。README.md はルート直下、main.ts と utils.ts は src/ フォルダの下にあります。この状態で git commit を実行すると、Git は index の内容をもとに tree オブジェクトと commit オブジェクトを自動作成します。
ステップ制御
進捗1 / 6
オブジェクト
blob3
tree0
commit0
refs0
GIT COMMIT 可視化STEP 1
CODE VIEW
# ディレクトリ構成:
.
├── README.md ← ルート直下
└── src/
├── main.ts ← src/ 配下
└── utils.ts ← src/ 配下
 
$ git ls-files --stage
100644 a9f3b7e... 0 README.md
100644 e4f5a6b... 0 src/main.ts
100644 c7d8e9f... 0 src/utils.ts
 
# git add 完了済み → ここから git commit の処理が始まります
blob(ファイル内容)
tree(ディレクトリ)
commit(スナップショット)
HEAD / ブランチ参照
GIT COMMIT ステップログ
1git commit 実行前の状態(git add 済み)
2git commit 実行 → tree 作成(src/)
3git commit の内部処理: root tree を作成
4git commit の内部処理: commit オブジェクトを作成
5git commit の内部処理: refs/heads/main を更新
6git commit 完了
解説

📌
git commit とは

git commit は、ステージングエリア(index)の内容を「スナップショット」として Git の履歴に確定するコマンドです。git add が「買い物かごに入れる」操作だったのに対し、git commit「レジで精算して受領書(コミット)をもらう」操作です。

一度コミットすれば、その時点のプロジェクト全体の状態がいつでも復元できるようになります。 ファイルを壊してしまっても、過去のコミットに戻ればいいので安心です。

コミットは「差分」ではなくプロジェクト全体のスナップショットです。 ただし Git は賢く、変更のないファイルは前のコミットの blob をそのまま再利用するので、容量は最小限で済みます。

⚙️
git commit の内部処理

「コミットする」の裏側では何が起きているのでしょうか? 具体的に覗いてみましょう。 Git は git commit を実行すると、内部で3つの処理を行っています。

1
index から tree オブジェクトを作成する
index のエントリをディレクトリごとにまとめ、sub-tree → root tree の順で tree オブジェクトを生成します。root tree がプロジェクト全体のスナップショットになります。
2
commit オブジェクトを作成する
root tree のハッシュ、parent commit(前のコミット)のハッシュ、author、committer、タイムスタンプ、コミットメッセージを含むオブジェクトを作成します。
3
ブランチ参照(refs)を更新する
HEAD が指すブランチ(例: .git/refs/heads/main)のファイルに、新しい commit のハッシュを書き込みます。これでブランチが新しいコミットを「指す」ようになります。

上のツールでステップを進めると、この3つの処理が順番に行われる様子を確認できます。

🧩
3つの領域

.git/index(ステージングエリア)
git add で登録されたファイルの一覧です。「ファイルパス → blob ハッシュ → パーミッション」を記録しています。git commit はこの index を読み取り、ディレクトリ構造に合わせて tree オブジェクトを組み立てます。
.git/objects/(オブジェクトデータベース)
blob・tree・commit の全オブジェクトが保存される場所です。git commit では、tree オブジェクト(ディレクトリ構造)と commit オブジェクト(スナップショットの記録)が新たに作られます。一度作られたオブジェクトは変更も削除もされません(イミュータブル)。
.git/refs/(ブランチ・タグの参照)
ブランチやタグが「どのコミットを指しているか」を記録するファイル群です。例えば .git/refs/heads/main には main ブランチが指す commit のハッシュが書かれています。git commit の最後に、このファイルが新しい commit のハッシュに書き換えられます。

🔍
commit オブジェクトの中身

commit オブジェクトはシンプルなテキストです。git cat-file -p [コミットハッシュ] で確認できます。

tree t4e5f6a
parent a1b2c3d
author Alice <alice@example.com> 1700000000 +0900
committer Alice <alice@example.com> 1700000000 +0900
 
Add project files
treeroot tree のハッシュ(プロジェクト全体のスナップショット)
parent親コミットのハッシュ(初回コミットにはなし。マージコミットは2つ)
author変更を書いた人 + タイムスタンプ(rebase しても変わらない)
committerコミットを実行した人 + タイムスタンプ(rebase で変わる)

🔑
ハッシュとは

可視化の中に出てくる f7e8d9c のような文字列がハッシュです。 Git はオブジェクト(blob・tree・commit)の中身をSHA-1 というアルゴリズムで計算し、40文字の英数字に変換します。

ハッシュはオブジェクトの「指紋」のようなもので、中身が同じなら必ず同じハッシュになり、1文字でも違えばまったく別のハッシュになります。 Git はこのハッシュを使ってオブジェクトを管理・参照しています。

# コミットのハッシュを確認する
$ git log --oneline
f7e8d9c
Add project files
 
# 実際は40文字(表示では先頭7文字に省略される)
f7e8d9c4a3b2e1f0d9c8b7a6e5f4d3c2b1a0f9e8
同じ内容 → 同じハッシュだから重複ファイルは自動的に1つの blob で済む
改ざん検知中身が変われば必ずハッシュが変わるので、データの破損や改ざんに気づける
ファイル名ではなく中身で管理ファイル名を変えても中身が同じなら同じ blob が再利用される

📂
.git/refs/ の中身

.git/refs/ は、ブランチやタグの情報が保存されているフォルダです。 例えば main ブランチなら .git/refs/heads/main、feature ブランチなら .git/refs/heads/feature というファイルが対応します。

中身を開くと驚くほどシンプルで、commit のハッシュが1行だけ書かれたテキストファイルです。

もうひとつ重要なファイルが .git/HEAD です。 これは refs/ の中ではなく .git/ 直下にあり、「今どのブランチで作業しているか」を記録しています。 git commit すると、Git はまず HEAD を見て「今 main ブランチにいる」と判断し、.git/refs/heads/main を新しい commit のハッシュに書き換えます。

# HEAD — 今いるブランチを記録
$ cat .git/HEAD
ref: refs/heads/main
 
# ブランチ — commit のハッシュが1行だけ
$ cat .git/refs/heads/main
f7e8d9c4a3b2e1f0d9c8b7a6e5f4d3c2b1a0f9e8

つまりHEAD → main → f7e8d9c → t4e5f6a(root tree)という参照チェーンでプロジェクト全体にたどり着けます。

.git/HEAD今チェックアウトしているブランチ名を記録(例: ref: refs/heads/main)
.git/refs/heads/mainmain ブランチが指す commit のハッシュ(git commit のたびに書き換わる)
.git/refs/heads/feature他のブランチも同じ構造。ブランチ作成 = ファイルを1つ作るだけ
.git/refs/tags/v1.0タグも同様にハッシュを記録したファイル(こちらは書き換わらない)

💻
コマンドとオプション

git commit -m "[メッセージ]"指定したメッセージでコミットする(エディタを開かない)
git commitエディタが開き、コミットメッセージを入力してコミットする
git commit -a -m "[メッセージ]"追跡済みファイルの変更を自動で git add してからコミットする
git commit --amend直前のコミットをやり直す(メッセージ変更やファイル追加)
git commit --allow-empty変更がなくても空のコミットを作成する(CI トリガー等に使用)
git commit -vエディタに diff を表示し、変更内容を確認しながらコミットする

⚠️
よくある失敗と対処法

コミットメッセージを間違えた
コミット直後にメッセージのタイポに気づいた場合。
$ git commit --amend -m "[正しいメッセージ]"
↑ 直前のコミットのメッセージだけを変更する(push 前に限る)
ファイルを入れ忘れてコミットした
コミット後に追加すべきファイルに気づいた場合。
$ git add [忘れたファイル]
$ git commit --amend --no-edit
↑ --no-edit でメッセージを変えずにファイルだけ追加する
直前のコミットを取り消したい
コミット自体をなかったことにしたい場合(push 前)。
$ git reset --soft HEAD~1
↑ --soft でコミットだけ取り消し、変更は staged のまま残る
push 済みのコミットを取り消したい
すでに push したコミットは reset ではなく revert で取り消す。
$ git revert HEAD
↑ 「取り消すコミット」を新たに作る(履歴は残る、安全)

関連コンテンツ