3つの場所とコミット — status・add・commit・diff
Git のファイルは、作業ツリー・ステージ・コミットの3つの場所にあります。git status の赤と緑も、git diff と git diff --cached の違いも、「どの場所とどの場所を比べているか」が分かれば読めます。この回では、ファイルを書き換えてからコミットするまでを1コマンドずつ追い、3つの場所の中身がどう動くかを見ていきます。Git が何をする道具なのかと、git init から最初のコミットまでは、1-0 Git は何をするものかで扱っています。
- 上のターミナルは、実際に打ったときの出力です(Git は英語で答えます)
- 下の中で起きていることは、コマンドの結果、Git の中の何が変わったかを図にしたものです。丸がコミット、黒い札がブランチ、ピンクの札が HEAD です
- 右の説明をスクロールして読み進めると、左のターミナルでコマンドが1つずつ打たれます。
→キーでも1つずつ進みます(←で1つ戻ります。スマホでは「次へ」ボタン)。最後まで進んでから→を押すと次の区間へ移ります。黄色く光っているのが、そのコマンドで変わった場所です
1. 3つの場所 — どこからどこへ写すか
Git で管理しているファイルは、同時に3つの場所に置かれています。
| 場所 | 何か | 中身を変えるコマンド |
|---|---|---|
| 作業ツリー | エディタで開いて見ている、ふつうのファイル | ファイルを編集する・rm で消す |
| ステージ(インデックス) | 「次のコミットにはこの中身を入れる」という置き場 | git add(作業ツリーから写す) |
| コミット | ある時点の全ファイルを撮った写真。一度撮ったら変わらない | git commit(ステージを写真に撮る) |
流れは一方通行です。ファイルを書き換えると作業ツリーが変わり、git add でステージに写り、git commit でステージが写真になります。コミットに入るのは、作業ツリーではなくステージの中身です。この1点が、この回のすべての場面に出てきます。
図の「3つの場所」の欄で、右端の「HEAD のコミット」は、いま乗っているブランチの最新のコミット(直前に撮った写真)のことです。
2. git status — 赤と緑を読む
git status は、3つの場所のうち隣どうしの差を見せるコマンドです。出力は最大3つの欄に分かれます。
| 欄の見出し | 色 | 比べているもの | 意味 |
|---|---|---|---|
Changes to be committed | 緑 | ステージ と HEAD のコミット | add 済み。次のコミットに入る |
Changes not staged for commit | 赤 | 作業ツリー と ステージ | 書き換えたが、まだ add していない |
Untracked files | 赤 | (ステージに無いファイル) | 一度も add していない新しいファイル |
ファイル名の前には、変わり方が付きます。modified は中身の変更、new file は新しく足したファイル、deleted は消したファイルです。3つの場所がどれも同じ中身なら、nothing to commit, working tree clean とだけ出ます。
git status の読み方
前の回でも打った
git statusを、詳しく読みます。git statusは、作業ツリー・ステージ・HEAD のコミットの3つを見比べて、どこに差があるか を教えるコマンドです。何かをする前とした後に、まずこれで今の状態を確かめます。3つの場所がどれも同じ中身のとき、
git statusはnothing to commit, working tree cleanと答えます。片付いている、という意味です。$ git status On branch main nothing to commit, working tree cleanファイルを書き換えます。変わるのは 作業ツリーだけ です。
$ echo "パンを買う" >> todo.txt赤字の
modifiedがChanges not staged for commitの下に出ました。これは 作業ツリーとステージの差 です。まだ add していない変更、という意味です。$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: todo.txt no changes added to commit (use "git add" and/or "git commit -a")git addで、作業ツリーの中身をステージに写します。$ git add todo.txt今度は緑の
Changes to be committedに移りました。これは ステージと HEAD のコミットの差 です。次のコミットに入る変更、という意味です。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: todo.txtadd したあとで、同じファイルにもう1行足します。
$ echo "バターを買う" >> todo.txt同じ
todo.txtが、緑と赤の 両方 に出ました。緑は add した「パン」まで、赤はそのあとに足した「バター」です。3つの場所の中身が、すべて違う状態です。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: todo.txt Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: todo.txtgit commitが写真に撮るのは ステージの中身 です。作業ツリーの「バター」は入りません。$ git commit -m "パンを追加" [main c43e6a8] パンを追加 1 file changed, 1 insertion(+)緑が消え、赤の「バター」だけが残りました。add していない変更は、コミットしても作業ツリーに残ったままです。
$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: todo.txt no changes added to commit (use "git add" and/or "git commit -a")
同じファイルが緑と赤の両方に出るのは、おかしなことではありません。add したあとにまた書き換えれば、そうなります。このままコミットすると、入るのは緑の側(add した時点の中身)だけです。
3. git add と git commit — 新しいファイルは一度 add する
add と commit には、よく使う書き方がいくつかあります。
| コマンド | 何をするか |
|---|---|
git add todo.txt | 指定したファイルだけをステージに写す |
git add . | 今いるフォルダの中の、変わったファイルを全部ステージに写す。追跡外の新しいファイルも、消したファイルも含む |
git commit -m "メッセージ" | ステージの中身で新しいコミットを作る |
git commit -am "メッセージ" | 追跡しているファイルの変更(削除を含む)をまとめて add してから、コミットする |
Git が追跡しているファイルとは、一度でも add してステージに入れたファイルのことです。作ったばかりのファイルは追跡外(Untracked)で、git commit -am の -a はこれを拾いません。
新しいファイルと git commit -am
新しいファイル
prices.txtを作ります。Git にとっては、まだ一度も add されていない 追跡外(Untracked)のファイルです。$ echo "牛乳は200円" > prices.txttodo.txtにも1行足します。$ echo "パンを買う" >> todo.txttodo.txtはmodified、prices.txtはUntracked filesの下に出ました。どちらも赤字ですが、意味が違います。追跡外のファイルは、ステージにも HEAD のコミットにも無いファイルです。$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: todo.txt Untracked files: (use "git add <file>..." to include in what will be committed) prices.txt no changes added to commit (use "git add" and/or "git commit -a")-aは「追跡しているファイル の変更をまとめて add してからコミットする」オプションです。-amは-aと-mをまとめた書き方です。$ git commit -am "パンを追加" [main c43e6a8] パンを追加 1 file changed, 1 insertion(+)prices.txtは取り残されました。-amは追跡外のファイルを拾いません。新しいファイルは、一度は自分で add します。$ git status On branch main Untracked files: (use "git add <file>..." to include in what will be committed) prices.txt nothing added to commit but untracked files present (use "git add" to track)git add .の.は「今いるフォルダの中の全部」です。追跡外のファイルも含めて、変わったものをまとめてステージに写します。$ git add .prices.txtが緑のnew fileになりました。ステージには入ったが、HEAD のコミットにはまだ無いファイルです。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: prices.txtprices.txtもコミットに入り、追跡されるファイルになりました。これ以降は-amでも変更を拾います。$ git commit -m "値段のメモを追加" [main d3c0aff] 値段のメモを追加 1 file changed, 1 insertion(+) create mode 100644 prices.txtコミットが2つ増えています。
$ git log --oneline d3c0aff (HEAD -> main) 値段のメモを追加 c43e6a8 パンを追加 8b41d07 卵を追加 3f2a9c1 牛乳を追加
-am は手軽ですが、新しいファイルは、最初の1回だけは自分で add する必要があります。コミットしたつもりのファイルが入っていないときは、まずここを疑ってください。
4. git diff と git diff --cached — 何がコミットに入るか
git status は「どのファイルが変わったか」までを見せます。中身がどう変わったかを見るのが git diff です。こちらも、どの2つの場所を比べるかで書き方が変わります。
| コマンド | 比べているもの | 見えるもの |
|---|---|---|
git diff | 作業ツリー と ステージ | まだ add していない変更 |
git diff --cached(--staged も同じ) | ステージ と HEAD のコミット | add 済みで、次のコミットに入る変更 |
--stat を付ける | (上と同じ) | 中身の代わりに、ファイルごとの変わった行数 |
--name-only を付ける | (上と同じ) | 変わったファイルの名前だけ |
git diff と git diff --cached
買い物メモ
todo.txtと、別のメモnotes.txtがあるリポジトリです。git statusは「どのファイルが変わったか」を見せます。git diffは「中身がどう変わったか」を見せます。todo.txtに1行足します。$ echo "パンを買う" >> todo.txtgit diffは 作業ツリーとステージ を比べます。+で始まる行が、足した行です。$ git diff diff --git a/todo.txt b/todo.txt --- a/todo.txt +++ b/todo.txt +パンを買うgit diff --cachedは ステージと HEAD のコミット を比べます。まだ何も add していないので、何も出ません。$ git diff --cachedadd すると、変更がステージに写ります。
$ git add todo.txt今度は
git diffが何も出さなくなりました。作業ツリーとステージが同じ中身になったからです。変更が消えたわけではありません。$ git diff変更は
--cachedの側に出ます。コミットする前に「何がコミットに入るか」を確かめるのは、こちらです。$ git diff --cached diff --git a/todo.txt b/todo.txt --- a/todo.txt +++ b/todo.txt +パンを買うnotes.txtにも1行足します。$ echo "特売は金曜も" >> notes.txt--statを付けると、中身の代わりに ファイルごとの変わった行数 だけが出ます。作業ツリーとステージの間で違うのはnotes.txtだけです。$ git diff --stat notes.txt | 1 + 1 file changed, 1 insertion(+)notes.txtも add します。$ git add notes.txtステージ側の行数です。次のコミットに2つのファイルが入ることが、一覧で分かります。
$ git diff --cached --stat notes.txt | 1 + todo.txt | 1 + 2 files changed, 2 insertions(+)--name-onlyは、ファイル名だけを出します。Claude Code がコミットの直前によく打つ確認です。$ git diff --cached --name-only notes.txt todo.txt確かめた2つのファイルが、1つのコミットに入りました。
$ git commit -m "パンと特売日を追加" [main 47dbb73] パンと特売日を追加 2 files changed, 2 insertions(+)
add したあとで git diff が何も出さなくなっても、変更は消えていません。作業ツリーとステージが同じになっただけで、変更は --cached の側に移っています。コミットの直前に確かめるべきなのは git diff --cached のほうです。
実際の画面では、この教材の端末より行が多く出ます。git diff には index … の行や、どのあたりの行が変わったかを示す @@ … @@ の行、変わっていない前後の行も出ます。--stat の最後の行も、0 件の側は省いて 1 file changed, 1 insertion(+) のように出ます。+ が足した行、- が消した行という読み方は同じです。
5. git restore --staged — add を取り消す
git add . は便利な反面、コミットするつもりのない下書きまで拾います。ステージに入れたものを外すのが git restore --staged ファイル です。
このコマンドは、指定したファイルのステージだけを、HEAD のコミットの中身に戻します。作業ツリーには触らないので、ファイルの中身は残ります。HEAD のコミットに無い新しいファイルなら、ステージから外れて追跡外に戻ります。
git restore --staged(add の取り消し)
todo.txtに1行足します。$ echo "パンを買う" >> todo.txtコミットするつもりのない下書き
draft.txtも、同じフォルダにあるとします。$ echo "まだ下書き" > draft.txtgit add .は全部を拾うので、下書きまでステージに入ってしまいます。$ git add .緑の欄に
draft.txtがnew fileとして出ています。このままコミットすると、下書きも入ります。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: draft.txt modified: todo.txtgit restore --stagedは、ステージだけを HEAD のコミットの中身に戻す コマンドです。add の取り消しにあたります。作業ツリーのdraft.txtには触りません。$ git restore --staged draft.txtdraft.txtは追跡外に戻りました。HEAD のコミットに無いファイルなので、ステージから外れたのです。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: todo.txt Untracked files: (use "git add <file>..." to include in what will be committed) draft.txtファイルの中身は残っています。消えたのは ステージに入っていた分 だけです。
$ cat draft.txt まだ下書きtodo.txtだけがコミットされました。add したら status を見て、余計なものがあれば外す。これがコミット前の確認の流れです。$ git commit -m "パンを追加" [main c43e6a8] パンを追加 1 file changed, 1 insertion(+)
同じことを、古い書き方では git reset HEAD ファイル と書きます。Claude Code の作業ログでも、git reset -q HEAD ファイル(-q は出力を省く指定)と git restore --staged の両方が出てきます。どちらも「add の取り消し」です。
6. 新しいファイルと、消したファイル
新しいファイルは、Untracked → add → commit の順で追跡されるファイルになります(3. の場面)。逆に、ファイルを消すときも同じ順番を踏みます。rm で消えるのは作業ツリーだけなので、「消した」という変更を add してから、コミットします。
ファイルを消してコミットする
使わなくなった
notes.txtを消します。rmはふつうのファイル削除なので、消えるのは 作業ツリーからだけ です。$ rm notes.txt赤字の
deletedが出ました。「作業ツリーから消えたが、ステージにはまだある」という意味です。$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: notes.txt no changes added to commit (use "git add" and/or "git commit -a")削除も変更の1つです。
-は消えた行を表します。$ git diff --stat notes.txt | 1 - 1 file changed, 1 deletion(-)消したファイルの名前を add します。「消した」という変更をステージに写す、ということです。
$ git add notes.txt緑の
deletedになりました。次のコミットでnotes.txtが無くなります。$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: notes.txt新しいコミットには
notes.txtがありません。それでも 前のコミットの写真には残っています。$ git commit -m "メモを消す" [main ebd4aa5] メモを消す 1 file changed, 1 deletion(-) delete mode 100644 notes.txt3つの場所がまた同じ中身になりました。
$ git status On branch main nothing to commit, working tree clean
消したファイルの add は、git add ファイル名 のほかに git add . や git commit -am でも拾われます。-a は追跡しているファイルの削除も拾うからです。
コミットから消えても、前のコミットの写真の中にはファイルが残っています。一方、一度もコミットしていない中身を rm で消すと、Git からは取り戻せません。
7. Claude Code はコミットの前に何を見ているか
Claude Code の過去の全セッションで実際に打たれた Git コマンドを数えると、この回のコマンドが上位を占めています(延べ約14,000回のうち)。
| 順位 | コマンド | 回数 | よく付くオプション |
|---|---|---|---|
| 1 | git status | 3,052 | |
| 2 | git diff | 2,628 | --stat(719)、--cached --stat(341)、--cached --name-only(243) |
| 3 | git add | 1,976 | |
| 5 | git commit | 1,490 |
(4位は、次の回で扱う git log です。)
並べると、Claude Code がコミットまでにしていることが読めます。
git statusとgit diff --statで、どのファイルが、どれくらい変わったかを見る(作業ツリー側)git addで、コミットに入れるファイルを選んでステージに写すgit diff --cached --statやgit diff --cached --name-onlyで、コミットに入るものが意図どおりかを確かめる(ステージ側)git commit -mでコミットする
--cached が付いているかどうかで、見ている場所が違います。許可画面や作業ログでこの並びを見かけたら、「いま作業ツリーを見ているのか、ステージを見ているのか」を当てはめてみてください。
8. Claude Code の許可画面で見かけたら
この回のコマンドは、ほとんどが「見るだけ」か「足すだけ」です。注意が要るのは、余計なものまで入るか、コミットしていない中身が消えるかの2点です。
| コマンド | 何が起きるか | 消えうるもの |
|---|---|---|
git status / git diff(--cached・--stat・--name-only) | 見るだけ | なし |
git add ファイル | 作業ツリーの中身をステージに写す | なし |
git add . | フォルダの中の変更をすべてステージに写す | 注意 消えるものはないが、コミットするつもりのないファイルまで入りうる |
git commit -m | ステージの中身で新しいコミットを足す | なし |
git commit -am | 追跡しているファイルの変更を全部 add してからコミット | 注意 消えるものはないが、別の作業の書きかけまでコミットに入りうる |
git restore --staged ファイル / git reset HEAD ファイル | ステージを HEAD の中身に戻す(add の取り消し。作業ツリーはそのまま) | 注意 add した後にさらに書き換えていたら、add した時点の版(ステージにだけあった中身) |
rm ファイル | 作業ツリーからファイルを消す | そのファイルの未コミットの中身(コミット済みの中身は前のコミットに残る) |
許可する前に見るのは、git add . や -am のときに、自分の書きかけのファイルが混ざらないかです。混ざっても、コミットする前なら git restore --staged で外せます。
次の回では、たまっていくコミットを読む git log と git show を扱います。
まとめ
- ファイルは作業ツリー・ステージ・コミットの3つの場所にある。add は作業ツリー→ステージ、commit はステージ→コミット
git statusの緑はステージと HEAD の差(次のコミットに入る)、赤は作業ツリーとステージの差(まだ add していない)、Untracked は一度も add していないファイルgit diffは作業ツリーとステージ、git diff --cachedはステージと HEAD を比べる。コミット前の確認は--cachedの側git commit -amは追跡外の新しいファイルを拾わない。新しいファイルは一度 add するgit restore --stagedは add の取り消し。作業ツリーの中身は残る- ファイルを消すときも、
rm→ add → commit の順。コミット済みの中身は前のコミットに残る