GIT VISUALIZER

git add

git add の内部動作をステップで可視化します。

初期状態
ワーキングディレクトリを確認
3つの未追跡ファイルがあります。まだ git add していないため、.git/objects にも .git/index にも何も記録されていません。git add を実行すると、Git はファイルの中身から SHA-1 ハッシュを計算し、blob オブジェクトとして保存します。
ステップ制御
進捗1 / 7
状態
WD ファイル3
Index エントリ0
Blob オブジェクト0
GIT ADD FLOWSTEP 1
CODE VIEW
On branch main
 
Untracked files:
(use "git add <file>..." to include in what will be committed)
 
README.md
src/main.ts
src/utils.ts
Working Directory
Index(ステージングエリア)
Blob オブジェクト
未追跡 / new
変更あり
古い blob
GIT ADD ステップログ
1ワーキングディレクトリを確認
2git add README.md
3git add src/main.ts
4git add src/utils.ts
5README.md を編集する
6git add README.md(再実行)
7git add 完了
解説

📌
git add とは

git add は、ファイルの変更を「次のコミットに含める準備をする」コマンドです。 Git ではファイルを保存しただけではコミットに含まれません。git add で明示的に「これをコミットに入れたい」と Git に伝える必要があります。

たとえるなら、買い物かごのようなものです。 お店(Working Directory)で商品(ファイル)を手に取っても、かご(ステージングエリア)に入れなければレジ(commit)では精算されません。git add は「かごに入れる」操作です。

このステージングエリアがあることで、変更したファイルの中から、コミットに含めたいものだけを選べるのが Git の大きな特徴です。 10個のファイルを変更しても、そのうち3つだけをコミットする、ということが簡単にできます。

流れ:ファイルを編集 → git add でステージ → git commit で確定

⚙️
git add の内部処理

「かごに入れる」と言いましたが、裏側では何が起きているのでしょうか? もう少し具体的に覗いてみましょう。 Git は git add を実行すると、内部で3つの処理を行っています。

1
ファイルの中身を読み取り、SHA-1 ハッシュを計算する
「blob <サイズ>\0<中身>」という形式でハッシュ値を算出。同じ内容なら世界中どの環境でも同じハッシュになります。
2
blob オブジェクトとして .git/objects/ に保存する
ファイルの中身を zlib 圧縮し、ハッシュの先頭2文字をディレクトリ名、残りをファイル名として保存します。
3
.git/index を更新する
「ファイルパス → blob ハッシュ」のマッピングを index ファイルに記録します。これが「ステージされた状態」です。
Working Dirgit add.git/indexhash.git/objects/

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

🧩
3つの領域

Working Directory(作業ディレクトリ)
実際にエディタで編集するファイルが置かれる場所。ユーザーが自由に変更できます。git status で「Changes not staged」と表示されるのは、ここの内容が index と異なるときです。
# 普通のファイルがそのまま置かれている
my-project/
├── index.html ← 編集中
├── style.css ← 新規作成
├── app.js
└── .git/
.git/index(ステージングエリア)
次の commit に含めるファイルの一覧を記録するバイナリファイル。「ファイルパス → blob ハッシュ → パーミッション」のマッピングを持ちます。git add するたびにこのファイルが更新されます。
# git ls-files --stage で中身を確認できる
100644 e69de29... 0 index.html
100644 a3f2c17... 0 style.css
100644 bd9dbf5... 0 app.js
↑ blob hash ↑ ファイルパス
.git/objects/(オブジェクトデータベース)
blob、tree、commit、tag の4種類のオブジェクトが保存される場所。git add では blob オブジェクトが作られます。一度作られたオブジェクトは変更も削除もされません(イミュータブル)。
# ハッシュの先頭2文字がディレクトリ名
.git/objects/
├── e6/9de29... ← blob(index.html の中身)
├── a3/f2c17... ← blob(style.css の中身)
├── bd/9dbf5... ← blob(app.js の中身)
├── info/
└── pack/

💻
コマンドとオプション

git add [ファイル]指定したファイルをステージする(blob 作成 + index 更新)
git add .カレントディレクトリ以下の全変更をステージする
git add -p [ファイル]ファイル内の変更を hunk 単位で選択してステージする(部分ステージ)
git add -A新規・変更・削除を含むすべての変更をステージする
git add -n [ファイル]実際にはステージせず、何が追加されるかをドライランで確認する
git reset [ファイル]ステージを取り消す(index のエントリを HEAD の状態に戻す。blob は残る)

⚖️
git add vs git commit

git addgit commit
作るオブジェクトblobtree + commit
更新するファイル.git/index.git/refs/heads/[ブランチ]
役割スナップショットの準備スナップショットの確定
取り消しgit reset [ファイル]git revert / git reset
繰り返し何度でもやり直せる履歴に残る(amend 以外)

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

不要なファイルを git add してしまった
.env や node_modules/ など、コミットすべきでないファイルをステージしてしまった場合。
$ git reset [ファイル]
↑ index からエントリを削除する(blob はオブジェクト DB に残るが、commit しなければ問題ない)
git add . で余計なファイルが入った
大量のファイルを一括ステージした後に、一部を取り消したい場合。
$ git reset
$ git add -p
↑ まず全ステージを取り消し、-p で対話的に選択し直す
.gitignore を後から追加した
すでに追跡済みのファイルは .gitignore に追加しても無視されない。
$ git rm --cached [ファイル]
$ echo "[ファイル]" >> .gitignore
↑ --cached で index からだけ削除(WD のファイルは残る)

🚫
.gitignore との関係

git add を実行すると、Git はまず .gitignore のルールをチェックします。 マッチするファイルは「未追跡」のままステージされないようになります。

ただし、すでに追跡済み(index に存在する)ファイルは .gitignore の対象外です。 追跡を止めるには git rm --cached で index から削除する必要があります。

# .gitignore
node_modules/
*.log
.env
dist/
$ git add . # 上記のファイルはステージされない
$ git add -f .env # -f で強制的にステージ(非推奨)

関連コンテンツ