git add後に同じファイルを再編集した時のstagedとunstagedを解説する記事のアイキャッチ。

開発現場メモ

git add後に同じファイルを編集するとどうなる?stagedとunstagedの違い

AIによる要約

git addはファイルを「今後ずっとコミット対象」にする操作ではなく、その時点の内容をステージング領域へ記録する操作です。add後に同じファイルを編集すると、add時点までの差分はstaged、その後の差分はunstagedとして同時に存在します。git diffで未ステージ差分、git diff --cachedでコミット予定差分を確認します。後の編集も同じコミットへ入れるなら再度git addし、分けるならそのままコミットします。

新人SE
新人SE
git statusで同じJavaファイルが2か所に出ました。Gitが壊れたのでしょうか?
ポンコツSE
ポンコツSE
正常な状態です。git addした時点の内容と、その後に編集した内容をGitが別の差分として管理しています。

新人がGitで混乱しやすいのは、「ファイル単位でステージされる」と考えてしまうことです。実際には、ワーキングツリー、ステージング領域、直前のコミットという3つの状態を比較しています。

同じファイルでも、変更の一部だけを次のコミットへ入れられます。この仕組みを理解すると、コミット漏れやデバッグコードの混入を防ぎやすくなります。

この記事のポイント

  • git addはその時点の差分をステージする
  • add後の編集は新しい未ステージ差分になる
  • git diffは未ステージ差分を表示する
  • git diff --cachedはコミット予定差分を表示する
  • コミット前にstatusと両方のdiffを確認する

XのGitクイズで状態を確認する

UserService.javaをgit addした後に同じファイルを再編集し、git statusの結果を問うGitクイズ画像。
git add後に同じファイルをもう一度編集すると、statusはどうなるでしょうか。
git add UserService.java

# UserService.javaをさらに編集
git status

同じ`UserService.java`が`Changes to be committed`と`Changes not staged for commit`の両方に表示されます。

同じUserService.javaがstagedとunstagedの両方へ表示され、git diff --cachedとgit diffで確認すると説明する回答画像。
add時点の差分と、その後の差分が別々に存在します。

Xの出題ポスト回答ポストも参照できます。

Gitで意識する3つの場所

場所意味
HEAD現在チェックアウトしている直前のコミット
ステージング領域次のコミットへ入れる内容
ワーキングツリーエディタで現在編集している内容

最初に編集すると、ワーキングツリーだけがHEADと異なる状態です。git addすると、その時点の内容がステージング領域へ記録されます。その後もう一度編集すると、ワーキングツリーだけがさらに先へ進みます。

HEAD
  UserService.java: version 1

git add後のステージング領域
  UserService.java: version 2

さらに編集したワーキングツリー
  UserService.java: version 3

この状態でコミットされるのはversion 2です。version 3の変更は手元に残り、次のコミット候補になります。

git diffとgit diff --cachedの違い

git diff

ワーキングツリーとステージング領域を比較します。つまり、まだgit addしていない変更を確認します。

git diff --cached

ステージング領域とHEADを比較します。つまり、今コミットした場合に入る変更です。`--staged`を使って`git diff --staged`と書いても同じ目的です。

コミット内容を確認する主役はgit diff --cachedです。git diffだけ見て「差分なし」と判断しないでください。

後の編集も同じコミットへ入れる場合

git add UserService.java
git status
git diff --cached
git commit -m "ユーザー更新処理を修正する"

もう一度git addすると、最新のワーキングツリー内容がステージング領域へ反映されます。statusで未ステージ側から消え、ステージ側だけになったことを確認します。

後の編集を次のコミットへ分ける場合

最初の修正だけを先にコミットしたいなら、再addせずにコミットします。コミット後も後半の編集はワーキングツリーに残ります。

git diff --cached
git commit -m "NullPointerExceptionを修正する"

git status
git diff

ただし前半だけでビルドやテストが通ることを確認してください。後半の編集がなければコンパイルできない状態をコミットすると、履歴の途中が壊れます。

ステージした内容を取り消す

git restore --staged UserService.java

ステージング領域から外し、変更自体はワーキングツリーへ残します。編集内容を捨てるコマンドではありません。実行後にstatusとdiffで確認します。

restoreの対象を確認する

`git restore --staged`はステージ解除ですが、`git restore ファイル名`はワーキングツリーの変更を戻します。未コミット変更を失う可能性があるため、オプションと対象を確認してから実行してください。

一部の変更だけステージする

git add -p UserService.java

`-p`を使うと、差分のまとまりごとにステージできます。同じファイルへバグ修正とリファクタリングが混ざった場合に、コミットを分けるために使えます。

ただし分割後のステージ内容が単独で正しいかを必ず`git diff --cached`で確認します。importだけ後のコミットに残した結果、先のコミットがコンパイルできない、といった事故があります。

現場でよくあるコミット事故

  • add後に消したデバッグログが、ステージ側には残っていた
  • 修正後に追加したimportを再addせず、CIでコンパイルエラーになった
  • git diffだけ確認し、古いステージ内容をそのままコミットした
  • 複数ファイルのうち1つだけ再addし、整合しない状態をpushした
  • IDEのチェックだけで、実際のステージ差分を確認しなかった

Gitは最後に保存したファイルを自動でコミットするわけではありません。ステージング領域にある内容がコミット対象です。IDEのGit画面を使う場合も、Staged ChangesとChangesのどちらを見ているか確認します。

コミット前の確認手順

  1. git statusで対象ファイルを確認する
  2. git diffで未ステージ差分を確認する
  3. git diff --cachedでコミット予定差分を確認する
  4. デバッグコード、秘密情報、不要ファイルがないか確認する
  5. ビルドとテストを実行する
  6. コミット後にgit statusでもう一度残りを確認する
git status
git diff
git diff --cached

# プロジェクトのテストを実行

git commit -m "注文検索条件を修正する"
git status

差分が大きい場合は、コミット前に`git diff --cached --stat`でファイル数と行数を見ると、意図しない大量変更に気づきやすくなります。

レビューへ出す前に履歴全体も見る

複数コミットをpushする場合、各コミットが正しくてもPR全体に不要差分が残ることがあります。ブランチの比較対象を確認し、レビュー画面または案件で定めたdiffコマンドで最終差分を見ます。

SES/SIer現場では、作業途中の設定ファイル、個人用IDE設定、ログ、接続先変更が混ざる事故もあります。git addを「保存ボタン」のように扱わず、コミットへ何を含めるか選ぶ操作として使います。

現場レビューでよくある指摘

// レビューコメント例
コミットにデバッグ用ログが残っています。
add後に削除した変更が再ステージされていない可能性を確認してください。

// レビューコメント例
UserServiceの修正に必要なimportが次コミットへ分かれており、
このコミット単体ではコンパイルできません。

// レビューコメント例
機能修正と無関係な整形差分が同じコミットに含まれています。
レビュー範囲を明確にするため分けてください。

コミット前のセルフチェック

  • git statusを確認したか
  • 同じファイルがstagedとunstagedの両方にないか
  • git diffで未ステージ差分を見たか
  • git diff --cachedでコミット予定差分を見たか
  • 後の編集を再addするか意図的に決めたか
  • デバッグコードや秘密情報がないか
  • コミット単体でビルド・テストできるか
  • コミット後の残差分を確認したか

Gitの操作を画面付きで学ぶ参考書

Gitの3領域や差分確認を図で整理したい場合は、手を動かしながら学べる入門書が役立ちます。

書籍「改訂2版 わかばちゃんと学ぶ Git使い方入門(Kindle版)」の表紙
商品画像:Amazon.co.jp
PR Git初心者向け Kindle版

改訂2版 わかばちゃんと学ぶ Git使い方入門(Kindle版)

湊川あい (著), DQNEO (著)

Gitの操作と考え方を、図解と会話でやさしく学ぶ。

コミット、ブランチ、マージ、競合など、新人が現場で戸惑いやすい操作を視覚的に確認できます。

  • Git操作への苦手意識を減らしたい
  • ブランチや競合の意味を理解したい

当サイトはAmazonアソシエイト・プログラムの参加者です。価格・在庫・配送条件はAmazonでご確認ください。

この記事とあわせて読みたい

まとめ

git addは、その時点のファイル内容を次のコミット候補としてステージする操作です。add後に編集すれば、同じファイルにステージ済み差分と未ステージ差分が共存します。

git diffで未ステージ差分、git diff --cachedでコミット予定差分を確認してください。後の編集も含めるなら再addし、分けるならコミット単体で成立することを確認してから進めましょう。

-開発現場メモ
-, ,