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 の読み方

  1. 前の回でも打った git status を、詳しく読みます。git status は、作業ツリー・ステージ・HEAD のコミットの3つを見比べて、どこに差があるか を教えるコマンドです。何かをする前とした後に、まずこれで今の状態を確かめます。

  2. 3つの場所がどれも同じ中身のとき、git status は nothing to commit, working tree clean と答えます。片付いている、という意味です。

    $ git status
    On branch main
    nothing to commit, working tree clean
  3. ファイルを書き換えます。変わるのは 作業ツリーだけ です。

    $ echo "パンを買う" >> todo.txt
  4. 赤字の 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")
  5. git add で、作業ツリーの中身をステージに写します。

    $ git add todo.txt
  6. 今度は緑の Changes to be committed に移りました。これは ステージと HEAD のコミットの差 です。次のコミットに入る変更、という意味です。

    $ git status
    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
    	modified:   todo.txt
    
  7. add したあとで、同じファイルにもう1行足します。

    $ echo "バターを買う" >> todo.txt
  8. 同じ 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.txt
    
  9. git commit が写真に撮るのは ステージの中身 です。作業ツリーの「バター」は入りません。

    $ git commit -m "パンを追加"
    [main c43e6a8] パンを追加
     1 file changed, 1 insertion(+)
  10. 緑が消え、赤の「バター」だけが残りました。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

  1. 新しいファイル prices.txt を作ります。Git にとっては、まだ一度も add されていない 追跡外(Untracked)のファイルです。

    $ echo "牛乳は200円" > prices.txt
  2. todo.txt にも1行足します。

    $ echo "パンを買う" >> todo.txt
  3. todo.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")
  4. -a は「追跡しているファイル の変更をまとめて add してからコミットする」オプションです。-am は -a と -m をまとめた書き方です。

    $ git commit -am "パンを追加"
    [main c43e6a8] パンを追加
     1 file changed, 1 insertion(+)
  5. 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)
  6. git add . の . は「今いるフォルダの中の全部」です。追跡外のファイルも含めて、変わったものをまとめてステージに写します。

    $ git add .
  7. prices.txt が緑の new file になりました。ステージには入ったが、HEAD のコミットにはまだ無いファイルです。

    $ git status
    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
    	new file:   prices.txt
    
  8. prices.txt もコミットに入り、追跡されるファイルになりました。これ以降は -am でも変更を拾います。

    $ git commit -m "値段のメモを追加"
    [main d3c0aff] 値段のメモを追加
     1 file changed, 1 insertion(+)
     create mode 100644 prices.txt
  9. コミットが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

  1. 買い物メモ todo.txt と、別のメモ notes.txt があるリポジトリです。git status は「どのファイルが変わったか」を見せます。git diff は「中身がどう変わったか」を見せます。

  2. todo.txt に1行足します。

    $ echo "パンを買う" >> todo.txt
  3. git diff は 作業ツリーとステージ を比べます。+ で始まる行が、足した行です。

    $ git diff
    diff --git a/todo.txt b/todo.txt
    --- a/todo.txt
    +++ b/todo.txt
    +パンを買う
  4. git diff --cached は ステージと HEAD のコミット を比べます。まだ何も add していないので、何も出ません。

    $ git diff --cached
  5. add すると、変更がステージに写ります。

    $ git add todo.txt
  6. 今度は git diff が何も出さなくなりました。作業ツリーとステージが同じ中身になったからです。変更が消えたわけではありません。

    $ git diff
  7. 変更は --cached の側に出ます。コミットする前に「何がコミットに入るか」を確かめるのは、こちらです。

    $ git diff --cached
    diff --git a/todo.txt b/todo.txt
    --- a/todo.txt
    +++ b/todo.txt
    +パンを買う
  8. notes.txt にも1行足します。

    $ echo "特売は金曜も" >> notes.txt
  9. --stat を付けると、中身の代わりに ファイルごとの変わった行数 だけが出ます。作業ツリーとステージの間で違うのは notes.txt だけです。

    $ git diff --stat
     notes.txt | 1 +
     1 file changed, 1 insertion(+)
  10. notes.txt も add します。

    $ git add notes.txt
  11. ステージ側の行数です。次のコミットに2つのファイルが入ることが、一覧で分かります。

    $ git diff --cached --stat
     notes.txt | 1 +
     todo.txt  | 1 +
     2 files changed, 2 insertions(+)
  12. --name-only は、ファイル名だけを出します。Claude Code がコミットの直前によく打つ確認です。

    $ git diff --cached --name-only
    notes.txt
    todo.txt
  13. 確かめた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 の取り消し)

  1. todo.txt に1行足します。

    $ echo "パンを買う" >> todo.txt
  2. コミットするつもりのない下書き draft.txt も、同じフォルダにあるとします。

    $ echo "まだ下書き" > draft.txt
  3. git add . は全部を拾うので、下書きまでステージに入ってしまいます。

    $ git add .
  4. 緑の欄に 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.txt
    
  5. git restore --staged は、ステージだけを HEAD のコミットの中身に戻す コマンドです。add の取り消しにあたります。作業ツリーの draft.txt には触りません。

    $ git restore --staged draft.txt
  6. draft.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
    
  7. ファイルの中身は残っています。消えたのは ステージに入っていた分 だけです。

    $ cat draft.txt
    まだ下書き
  8. 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 してから、コミットします。

ファイルを消してコミットする

  1. 使わなくなった notes.txt を消します。rm はふつうのファイル削除なので、消えるのは 作業ツリーからだけ です。

    $ rm notes.txt
  2. 赤字の 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")
  3. 削除も変更の1つです。- は消えた行を表します。

    $ git diff --stat
     notes.txt | 1 -
     1 file changed, 1 deletion(-)
  4. 消したファイルの名前を add します。「消した」という変更をステージに写す、ということです。

    $ git add notes.txt
  5. 緑の deleted になりました。次のコミットで notes.txt が無くなります。

    $ git status
    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
    	deleted:    notes.txt
    
  6. 新しいコミットには notes.txt がありません。それでも 前のコミットの写真には残っています。

    $ git commit -m "メモを消す"
    [main ebd4aa5] メモを消す
     1 file changed, 1 deletion(-)
     delete mode 100644 notes.txt
  7. 3つの場所がまた同じ中身になりました。

    $ 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回のうち)。

順位コマンド回数よく付くオプション
1git status3,052
2git diff2,628--stat(719)、--cached --stat(341)、--cached --name-only(243)
3git add1,976
5git commit1,490

(4位は、次の回で扱う git log です。)

並べると、Claude Code がコミットまでにしていることが読めます。

  1. git status と git diff --stat で、どのファイルが、どれくらい変わったかを見る(作業ツリー側)
  2. git add で、コミットに入れるファイルを選んでステージに写す
  3. git diff --cached --stat や git diff --cached --name-only で、コミットに入るものが意図どおりかを確かめる(ステージ側)
  4. 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 の順。コミット済みの中身は前のコミットに残る