コミットを「ごちゃ混ぜ」にしないために
よくあるシナリオ:重大なバグを修正している最中に、隣にある数行のコードが気になってついでにリファクタリングしてしまう。さらに、コメントを追記し、不要なconsole.logを削除する。git statusを確認すると、1つのファイルで3つの異なる目的のために100行もの変更が加えられています。
もしgit add .を実行して「Fix bug and refactor」というメッセージでコミットしてしまうと、後で苦労することになります。コードレビュアー(あるいは数ヶ月後の自分)は、その混沌とした変更の中から、どこがバグ修正のメインロジックなのかを探し出さなければなりません。すべてを1つのコミットにまとめると、エラーの追跡は悪夢に変わります。
git add -p(–patchの略)は、このような場合の救世主です。このコマンドを使うと、変更箇所を小さな単位(hunk)ごとに確認し、ステージングエリアに含めるかどうかを判断できます。プロフェッショナルにコードを整理していきましょう。
クイックスタート:5分でマスターするgit add -p
例えば、app.pyで計算ロジックと表示形式の両方を修正したとします。ファイル全体をaddする代わりに、次のコマンドを入力します:
git add -p app.py
Gitはファイルを変更箇所(hunkと呼ばれます)ごとに分割し、どのように処理するかを尋ねてきます:
Stage this hunk [y,n,q,a,d,j,J,g,/,s,e,?]?
羅列された文字に戸惑う必要はありません。実際には、90%のケースで以下の4つの基本キーを覚えておくだけで十分です:
- y (yes): この hunk を現在のコミットに含める。
- n (no): この hunk をスキップして、次のコミットに回す。
- s (split): 現在の hunk にバグ修正とリファクタリングの両方が含まれている場合、
sを押してさらに細かく分割する。 - q (quit): 終了する。これ以上追加しない。
選択が終わったら、git commit -m "Fix: 消費税計算ロジックの修正"のように選択した部分だけをコミットします。nを押した部分はunstaged(未ステージ)のまま残り、別の内容でコミットする準備が整った状態になります。
操作を高速化する高度なオプション
y/n/sに慣れてきたら、ナビゲーションキーを使って数千行に及ぶ大きなファイルの処理速度を上げることができます:
1. ‘s’キーで徹底的に分割する
Gitは近くにある変更行を自動的に1つの hunk にまとめます。10行の中に5行のバグ修正と5行のコメント追加がある場合、sキーを押すと、その間にある変更のない行を基準に分割を試みます。
2. スマートなナビゲーション (j, J, g)
- j: この hunk を未決定のままにして、次の hunk にジャンプする。
- k: 前の hunk に戻る。
- g: リスト内の特定の hunk に素早くジャンプする。
3. 一括決定 (a, d)
- a (all): この hunk とファイル内の残りのすべての hunk をステージングする。
- d (don’t): この hunk とファイル内の残りのすべての hunk をスキップする。
“Edit”モード:’e’キーで1行単位の編集を行う
変更箇所が隣接している場合など、s(split)コマンドでは思うように分割できないことがあります。その場合は、e (edit)を押して手動で介入します。
Gitがエディタ(VimやNanoなど)を開きます。+(追加)と-(削除)で始まる行が表示されます。
- 追加した行をこのコミットから除外したい場合は、その行を削除します。
- 削除する予定だった行を残したい場合は、
-記号を半角スペースに置き換えます。
重要な注意点:このモード中にコードの内容自体を変更しないでください。「patch does not apply」エラーを避けるため、行を削除するか行頭の記号を変更するだけに留めてください。
なぜこれがシニアエンジニアの習慣なのか?
実際のプロジェクトでは、500行のごちゃ混ぜなコードを含むプルリクエスト(PR)は、同僚のレビューに1時間以上かかってしまいます。もし5つの小さなコミットに分け、各コミットが1つの問題に集中した100行程度であれば、レビュー時間は30%短縮できるでしょう。
git add -pを使うことで、3つの実質的なメリットが得られます:
- セルフレビュー: 自分のコードを1行ずつ見直すことになります。この時、不要な変数や消し忘れた
print(data)に気づくことができます。 - アトミックコミット(Atomic Commits): 各コミットが1つのことだけを解決します。リファクタリング部分でバグが発生しても、重要なバグ修正を失うことなくその部分だけを
git revertできます。 - Git Bisectによる超速デバッグ: コミットを細かく分けることで、
bisectコマンドを使ってエラーの原因となった正確な行を数倍速く特定できます。
他のGitコマンドとの連携テクニック
git commit -v で最終確認
ステージングが終わったら、次のコマンドを試してみてください:
git commit -v
このコマンドは、メッセージ入力画面のすぐ下にコミットしようとしているコードの内容をすべて表示します。プロジェクトの履歴に「ゴミ」が混入しないことを100%確信できます。
不要な変更を破棄する (git checkout -p)
実験的に書いたいくつかのコードを削除したいが、同じファイル内の他の部分は残したい場合は、次のように入力します:
git checkout -p filename.py
仕組みはgit add -pと全く同じですが、ステージングする代わりに、yを選択することでその箇所の変更を破棄(discard)します。ファイルはすぐにクリーンな状態に戻ります。
結論
git add -pを使い始めると、最初の数日は作業が少し遅くなったように感じるかもしれません。しかし、長期的には、丁寧でプロフェッショナルな思考プロセスを構築してくれます。ただ動くコードを書くコーダーではなく、ソースコードを芸術的に管理できるエンジニアを目指しましょう。

