AIに不具合修正を頼んだら、同じファイルの整形とREADMEの書き換えまで入っていた。ファイル単位でcommitすると、修正理由が一つにまとまらないことがあります。
まだcommitしていない変更なら、git add -pで変更の塊を選び、関連するテストと一緒にcommitします。すでに一つのcommitへ入れた場合は、自分だけが使う未共有の履歴に限り、rebaseのeditで止めて分割できます。
このページでは、変更内容を残したままstageを選び直す手順と、分割したcommit単体を確認する方法を扱います。Git 2.55.0・Node.js 24.13.0の独立した検証リポジトリで操作を確認しました。コマンド中のパスとテストは例なので、自分の対象へ置き換えてください。
ファイル名より、変更の目的と依存関係で分ける
最初に、AIの差分へ入ったものを見ます。もともと自分やほかの人が編集していた変更があるなら、それも含めた全体をAIの成果として扱いません。
git status --short
git diff --stat
git diff -- src/pricing.mjs
git diff --staged
今回の例は、数量が負の場合を拒否する修正、同じファイル内の引用符の整形、READMEへのテスト実行方法の追記です。次のように目的を分けます。
| commit | 含める変更 | 一緒に確かめること |
|---|---|---|
| 負の数量を拒否する | 条件判定と、その挙動を確かめるテスト | 通常の計算と負の数量の両方 |
| 表記を整える | 同じファイルの引用符の変更 | 前のcommitと挙動が同じか |
| テスト手順を記す | READMEの追記 | 記載したコマンドが実行できるか |
整形・移動・挙動変更は分ける候補になりますが、機械的に3分類へ押し込む必要はありません。関数を移すならimport先の変更も必要です。不具合修正に必須のテストや設定を別commitへ追い出すと、途中のcommitが壊れます。「一つずつ読める」ことと「一つずつ動く」ことを両方満たす単位を選びます。
git add -pで、修正する塊だけをstageする
hunkは、diffに表示される変更の塊です。同じファイルでもhunkを選べるため、ファイル全体をaddする前に次を実行します。
git add -p -- src/pricing.mjs
たとえば次の差分では、負の数量を拒否する行だけを最初のcommitへ入れ、引用符の変更は後へ残したい状態です。
export function total(price, quantity) {
+ if (quantity < 0) throw new RangeError('negative quantity');
return price * quantity;
}
export function currency() {
- return 'JPY';
+ return "JPY";
}
二つが一つのhunkで出たらsで分けます。修正の塊でy、引用符の塊でnを選びます。表示順や分割可能な箇所は実際の差分によるので、キーの並びを見ずに流し込まないでください。
| キー | 操作 |
|---|---|
| y | いまのhunkをstageする |
| n | いまのhunkを今回はstageしない |
| s | 分割できるhunkを、さらに小さく分ける |
| e | エディターでstageするpatchを編集する |
| q | 残りを選ばず終了する。すでに選んだ分まで全取消する操作ではない |
| ? | 操作の説明を表示する |
sで分けられない場合は、eでpatchを編集できます。stageしない追加行はpatchから削り、stageしない削除行は先頭の「-」を空白へ戻します。置換を外すなら、削除側と追加側の両方を調整します。これは作業ファイルの編集ではなく、indexへ適用するpatchの編集です。
手動編集では、indexだけが作業ファイルとも元のcommitとも違う中間状態になり得ます。適用できない場合や内容を判断できない場合は、無理に確定せず選び直します。操作後は、次の二つを必ず読みます。
git diff --staged -- src/pricing.mjs
git diff -- src/pricing.mjs
上が次のcommitへ入る差分、下がまだ入らない差分です。さらに、実装と対応するテストをstageします。テストファイルにも別目的の変更が混じっているなら、そちらも-pで選びます。
git add -- tests/pricing.test.mjs
git diff --staged
git diff --staged --check
git commit -m "Reject negative quantity"
この手順では、commitに-aやファイル名を追加しません。選んだindexの内容をcommitしたい場面で別のstage方法を混ぜると、残すつもりだった変更まで含める原因になります。未追跡の新規ファイルを部分stageしたい場合は、git add -N -- path/to/new-fileで存在をindexへ知らせてから、git add -p -- path/to/new-fileを使えます。
選びすぎたときは、作業内容を消さずにstageだけ外す
整形のhunkまでyにしてしまった場合、commit前ならstageを選び直せます。部分的に外すコマンドは次です。
git restore --staged -p -- src/pricing.mjs
git diff --staged -- src/pricing.mjs
git diff -- src/pricing.mjs
今回は外したいhunkを選びます。通常のHEADがあるリポジトリでは、–stagedによってindexをHEAD側へ戻し、作業ファイルの編集は残します。そのファイルのstageを全部外すなら、git restore --staged -- src/pricing.mjsです。
–stagedを付けないgit restore -pは、作業ファイルの変更を戻す操作です。分割のためのstage解除と混同しないでください。最初からstage済みだった他の人の変更がある場合も、ファイル全体をまとめて外さず、対象を確認して部分的に扱います。
分けたcommitだけを、別のworktreeでテストする
手元の作業ファイルには、まだcommitしていない整形や追加処理が残っています。その状態でテストが通っても、直前に作ったcommit単体が通るとは限りません。必要な関数をstageし忘れた場合でも、作業ファイルには関数があるため見逃せます。
一つ目をcommitした後、未使用のパスへそのcommitだけのworktreeを作ります。下の例はNode標準のテストを使うため、追加の依存インストールは不要です。
git worktree add --detach ../review-fix HEAD
node --test ../review-fix/tests/pricing.test.mjs
git -C ../review-fix status --short
git worktree remove ../review-fix
自分のプロジェクトでは、そのworktreeに入って規定の依存準備・テスト・ビルドを行います。元の作業フォルダーのnode_modulesへ無理に依存させず、検証条件をそろえてください。worktreeの削除を拒否されたら、残った変更を確認し、forceで捨てないようにします。
検証で失敗したら、必要な変更を最初のcommitへ含め直すなど、分け方を修正します。通過したら、残った整形、READMEを順にcommitし、それぞれ確認します。
git add -- src/pricing.mjs
git diff --staged
git commit -m "Format currency literal"
# このcommit単体を確認してから、次へ進む
git add -- README.md
git diff --staged
git commit -m "Document test command"
検証例では、修正・整形・文書の各commitを別worktreeでテストし、すべて通ることを確認しました。実案件でgit addをファイル全体に使うのは、その時点の残りが当該目的だけだと確認できた場合です。
未共有のcommitを分割するときは、editで止める
次は、すでに「修正+整形+文書」を一つのcommitへまとめ、その後に別のcommitも作ったケースです。自分だけの未共有ブランチで、マージを含まない直線の履歴を前提にします。共有済みの履歴や、誰の変更か分からない作業へこの手順をそのまま使いません。
最初に未commit変更と未追跡ファイルがないことを確認します。ある場合は、先に自分の作業を保存・整理します。backupブランチが保存するのはcommit済みの履歴であり、未commitの編集ではありません。
git status --short
git log --oneline -n 5
git branch backup/ai-split-before
git rebase -i HEAD~2
HEAD~2は、今回の「大きいcommit+その後のcommit」の2本を対象にする指定です。自分の履歴に合わせて範囲を選びます。開いた一覧では、分割するcommitの先頭のpickをeditへ替え、後続のcommitはpickのまま保存します。
対象commitで停止したら、次を実行します。–mixedはHEADとindexを一つ前へ戻し、作業ファイルには対象commitの内容を残します。–hardへ替えないでください。
git reset --mixed HEAD^
git add -p -- src/pricing.mjs
git add -- tests/pricing.test.mjs
git diff --staged
git commit -m "Reject negative quantity"
# 残りも、差分と単体動作を確認してcommitする
git add -- src/pricing.mjs
git commit -m "Format currency literal"
git add -- README.md
git commit -m "Document test command"
git status --short
git rebase --continue
続行前には、分ける対象の変更がすべてcommitされ、作業フォルダーが整理できていることを確認します。rebase –continueで後続のcommitが再適用されます。競合したら、何を残すかを確かめて解消し、解消したファイルをaddして続行します。
途中で元へ戻すならgit rebase –abortを使えます。ただし、中断中に加えた編集もそのまま残るとは考えず、必要な新しい作業があれば別途保全してから中止します。commitを分ける以外の編集を同時に始めないと、戻す対象を把握しやすくなります。
最後に、分割前の先端とファイル内容を比較します。
git diff --exit-code backup/ai-split-before HEAD
git log --oneline -n 6
git status --short
内容を変えず分割できたなら、最初のdiffは空になり終了コードは0です。検証例でも、後続commitを再適用した後の最終内容が一致しました。これは途中のcommitが動くことまで保証しないため、先ほどの単体テストと併せて確認します。
次回AIへ依頼するときは、「今回は不具合修正と対応テストだけ。整形・ファイル移動・文書改善の提案は、変更せず別に列挙してください」と範囲を先に伝えられます。それでも実際のdiffを確認し、既存の編集と混ざっていないかを見ます。分割後の文面を整える段階は、AIでコミットメッセージを作る方法を参照してください。
公式の操作説明:git addの対話操作、git restoreの対象領域、git rebaseのコミット分割(2026年9月12日確認)。