0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【図解でわかるGit 第1回】ワークツリー・ステージ・リポジトリの3層構造を完全理解する

0
Posted at

株式会社Good Labでエンジニアをしている kotaro です。
日々、Java・SQL・Gitなどの技術情報や、新人エンジニア向けの学習ノウハウ、
AI活用についての情報を発信しています。

Good Labについて気になった方は、コーポレートサイトもぜひご覧ください。
コーポレートサイト


はじめに

この記事は 「図解でわかるGitの仕組み」シリーズ の第1回です。
Gitの内部構造を、1テーマ1記事で図解していきます。

git addgit commit の違いがよくわからない」
「なぜ一発でコミットできないの?ステージングって何のためにあるの?」

Gitを使い始めたころ、こんな疑問を持ちませんでしたか?

この記事では、Gitの 3層構造(ワークツリー・ステージングエリア・リポジトリ) を図解で丁寧に解説します。読み終わるころには、git addgit commitどこからどこへデータを移しているのか を明確に説明できるようになります。


1. Gitの全体像 ― 3つのエリア

Gitでファイルを管理するとき、データは 3つのエリア を移動します。

01_three_areas_overview.png

エリア 別名 場所 役割
ワークツリー Working Directory / Working Tree プロジェクトフォルダそのもの ファイルを編集する場所
ステージングエリア インデックス(Index) .git/index ファイル 次のコミットに含める変更を選ぶ場所
ローカルリポジトリ リポジトリ(Repository) .git/objects/ 配下 コミット履歴を永続的に保存する場所

この3つのエリアを理解することが、Git理解の第一歩です。


2. 各エリアの詳細

ワークツリー(Working Tree)

ワークツリーとは、あなたが 実際にファイルを編集する場所 です。エディタで開いて書き換えているファイルは、すべてワークツリー上にあります。

my-project/          <-- ここがワークツリー
├── .git/            <-- Gitの管理データ(後述)
├── src/
│   └── Main.java
├── README.md
└── .gitignore

Git公式用語集(gitglossary)では、ワークツリーを次のように定義しています。

The tree of actual checked out files. The working tree normally contains the contents of the HEAD commit's tree, plus any local changes that you have made but not yet committed.
(実際にチェックアウトされたファイルのツリー。通常、HEADコミットのツリーの内容に、まだコミットしていないローカルの変更を加えたものが含まれる)

つまりワークツリーは「最新のコミット内容 + あなたが今書き換えた部分」の合計です。

ステージングエリア(Staging Area / Index)

ステージングエリアは、次のコミットに含める変更を選別する中間エリア です。

Git内部では index とも呼ばれ、実体は .git/index というバイナリファイルです。git add コマンドで、ワークツリーの変更をステージングエリアに登録します。

# ワークツリーの変更をステージングエリアに追加
git add Main.java

ローカルリポジトリ(Local Repository)

ローカルリポジトリは、コミット履歴が永続的に保存される場所 です。

git commit コマンドで、ステージングエリアの内容がスナップショットとしてリポジトリに記録されます。すべてのコミットオブジェクトは .git/objects/ ディレクトリ配下に格納されます。

# ステージングエリアの内容をリポジトリに記録
git commit -m "Mainクラスを追加"

3. データの流れ ― git addgit commit

3つのエリア間でデータがどう移動するかを見てみましょう。

01_data_flow_add_commit.png

ワークツリー  ──git add──▶  ステージングエリア  ──git commit──▶  ローカルリポジトリ
 (編集する)                    (選別する)                          (記録する)
コマンド 移動の方向 何が起きるか
git add ワークツリー → ステージングエリア 変更をステージに登録する
git commit ステージングエリア → ローカルリポジトリ ステージの内容をスナップショットとして記録する

実際にやってみる

# 1. リポジトリを作成
mkdir my-project && cd my-project
git init

# 2. ファイルを作成(ワークツリーに変更が発生)
echo "Hello, Git!" > hello.txt

# 3. 状態を確認 ― hello.txt は「Untracked」
git status
# 出力:
# Untracked files:
#   hello.txt

# 4. ステージングエリアに追加
git add hello.txt

# 5. 状態を確認 ― hello.txt は「Changes to be committed」に移動
git status
# 出力:
# Changes to be committed:
#   new file:   hello.txt

# 6. コミット(リポジトリに記録)
git commit -m "最初のコミット: hello.txtを追加"

# 7. 状態を確認 ― ワークツリーもステージもクリーン
git status
# 出力:
# nothing to commit, working tree clean

# 8. コミット履歴を確認
git log --oneline
# 出力例:
# a1b2c3d 最初のコミット: hello.txtを追加

git status の出力が変化していく様子から、ファイルが3つのエリアを移動していることがわかります。


4. .git ディレクトリの正体

git init を実行すると、プロジェクト直下に .git ディレクトリが作成されます。このディレクトリこそがリポジトリの本体です。

# .git ディレクトリの中身を確認
ls .git/
HEAD            # 現在チェックアウトしているブランチへの参照
config          # リポジトリ固有の設定
description     # GitWebで使われる説明文(通常は使わない)
hooks/          # コミット前後に実行するスクリプト
index           # ステージングエリアの実体
info/           # リポジトリ固有の除外ルール(exclude ファイル等)
objects/        # すべてのGitオブジェクト(コミット・ツリー・ブロブ)
refs/           # ブランチやタグが指すコミットのポインタ

01_dot_git_directory.png

特に重要なファイル・ディレクトリは以下の3つです。

パス 役割
.git/index ステージングエリアの実体。git add するとこのファイルが更新される
.git/objects/ コミット・ツリー・ブロブの各オブジェクトが格納される場所
.git/HEAD 現在のブランチを指すポインタ(例: ref: refs/heads/main

.git ディレクトリを削除すると、すべてのコミット履歴が失われます。 このディレクトリだけは絶対に手動で操作しないでください。


5. なぜステージングエリアが必要なのか

「ワークツリーから直接コミットすればいいのでは?」と思うかもしれません。ステージングエリアが存在する理由を、実例で説明します。

理由1: コミットの粒度をコントロールできる

たとえば、1つの作業で3つのファイルを変更したとします。

変更したファイル:
  - src/Login.java       (ログイン機能のバグ修正)
  - src/Dashboard.java   (ダッシュボードのレイアウト変更)
  - src/Login.java のテスト(テスト追加)

これを 1つのコミットにまとめる と、後から「バグ修正だけ取り消したい」というときに困ります。

ステージングエリアがあれば、関連する変更だけを選んでコミットできます。

# バグ修正だけを先にコミット
git add src/Login.java
git commit -m "fix: ログイン時のnullチェックを追加"

# レイアウト変更を別のコミットにする
git add src/Dashboard.java
git commit -m "feat: ダッシュボードのレイアウトを変更"

このように、意味のある単位でコミットを分けることで、履歴が読みやすくなり、レビューや git revert も容易になります。

理由2: 同じファイルの一部だけをコミットできる

git add -p(パッチモード)を使うと、1つのファイル内の変更を行単位で選択してステージできます。

# ファイルの変更を行単位で選択してステージ
git add -p src/Login.java

これは「デバッグ用のログ出力を残したまま、本来の修正だけコミットしたい」といった場面で非常に便利です。

理由3: コミット前にレビューできる

ステージングエリアは「これからコミットする内容」の確認場所としても機能します。

# ステージした内容を確認(コミット前レビュー)
git diff --staged

このコマンドで、実際にコミットされる差分だけを確認できます。


6. git status の読み方

git status は、3つのエリアの状態を一覧表示するコマンドです。出力の意味を正確に理解しましょう。

git status
On branch main
Changes to be committed:            ← ステージングエリアにある変更
  modified:   src/Login.java

Changes not staged for commit:       ← ワークツリーにあるがステージされていない変更
  modified:   src/Dashboard.java

Untracked files:                     ← Gitが追跡していない新規ファイル
  docs/setup.md

01_git_status_mapping.png

セクション 意味 次のアクション
Changes to be committed ステージ済み。次の git commit で記録される git commit でコミット
Changes not staged for commit ワークツリーで変更済みだがステージされていない git add でステージに追加
Untracked files Gitの管理対象外の新規ファイル git add で追跡を開始

7. 逆方向の操作 ― 変更を戻す

ここまでは「ワークツリー → ステージ → リポジトリ」という順方向の流れを見ました。逆方向の操作も確認しておきましょう。

01_reverse_operations.png

ローカルリポジトリ  ──git restore --staged──▶  ステージングエリア(HEADの内容で上書き)
ステージングエリア  ──git restore──▶  ワークツリー(ステージの内容で上書き)
やりたいこと コマンド
ステージを取り消す(ステージ → ワークツリーに戻す) git restore --staged <file>
ワークツリーの変更を破棄する(最後のコミット状態に戻す) git restore <file>
# ステージを取り消す(ファイルの変更はワークツリーに残る)
git restore --staged src/Login.java

# ワークツリーの変更を破棄する(変更が完全に消えるので注意)
git restore src/Login.java

git restore <file>ワークツリーの変更を完全に破棄します。コミットしていない変更は復元できないため、実行前に本当に不要か確認してください。


8. まとめ

この記事で学んだポイントを整理します。

項目 ポイント
3つのエリア ワークツリー → ステージングエリア → ローカルリポジトリ
git add ワークツリーの変更をステージングエリアに登録する
git commit ステージングエリアの内容をリポジトリに記録する
.git ディレクトリ リポジトリの本体。ステージ(index)もコミット履歴(objects/)もここにある
ステージの存在意義 コミットの粒度をコントロールし、意味のある単位で履歴を残すため
git status 3つのエリアの状態を一覧で確認できるコマンド
git restore 変更の取り消し。--staged でステージ解除、なしでワークツリーの変更を破棄

次回予告

第2回では 「ブランチとHEAD」 を図解で解説します。「ブランチは枝分かれ」というイメージがありますが、実際には コミットを指すポインタ にすぎません。HEADとは何か、ブランチの切り替えで何が起きるのかを、内部構造から理解します。


シリーズ目次

# テーマ
1 Gitの全体像 ― ワークツリー・ステージ・リポジトリの3層構造(この記事)
2 ブランチとHEAD ― 「枝分かれ」の正体を理解する
3 マージとリベース ― 統合戦略の違いを図で比較
4 リモートとローカル ― push/pull/fetchの裏側
5 コンフリクト解消 ― なぜ起きるのか、どう直すのか
6 reset/revert/checkout ― 「戻す」操作を正しく使い分ける
7 stash/cherry-pick/rebase -i ― 実務で頼れる便利コマンド
8 .gitignore・フック・設定 ― Gitをカスタマイズする
9 Git Flow vs GitHub Flow ― ブランチ戦略の選び方
10 トラブルシューティング ― 「やらかした!」を救うコマンド集

参考


「この記事が役に立った」と思ったら、LGTM とストックをお願いします。

@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?