前回のDay 27では、巨大なC#ソリューションでの再ビルド待ちを完全ゼロにする神機能「git worktree」の内部構造と2画面並行デバッグの極意を学びました。
そして本日のDay 28は、プロの現場で毎日のように使われる超実践テクニック——【git add -p で必要な行だけを綺麗にコミットする部分ステージング技】を徹底解説します!
「C#のバグ調査や新機能開発の際、変数の値を確認するためにコードの途中に
Console.WriteLine を差し込んだり、一時的なハードコード(テスト用の固定値やフラグ)を書き込むことはよくありますよね」「しかし、いざコミットしようとしたとき、そのデバッグ行を手動で1行ずつ削除したりコメントアウトして、再度ビルド確認してからコミットしていませんか? あるいは、削除し忘れたデバッグログがそのまま本番リポジトリにコミットされ、Pull Requestのレビューで『不要なデバッグ出力が残っていますよ』と指摘されて恥ずかしい思いをしたことはありませんか?」
かつてのSubversion (SVN) では「ファイル単位」でしかコミット対象を選択できなかったため、そうした苦労は避けられませんでした。
しかしGitには、1つのファイル内にある変更箇所を行単位(Hunk:ハンク)で自由自在に選別し、必要な行だけをインデックス(ステージング)に載せる『git add -p (patch)』という強力無比な機能が備わっています!
ローカルのデバッグ用ログを残したまま、本番用修正コードだけを100%美しくコミットするプロの極意を、コマンドラインとTortoiseGit GUIの両面から完全マスターしましょう!
① 導入・本日の達成目標
現場で優れたエンジニアと評価される基準の1つに、「コミット履歴の美しさ(Atomic Commit:単一責務のコミット)」があります。
1つのコミットに「本番のバグ修正」と「関係のない一時デバッグコード」や「ついでに行った別機能のリファクタリング」がごちゃ混ぜになっていると、コードレビューの負担が跳ね上がり、将来障害が発生して git revert や git bisect を行う際にも大きな事故の原因になります。
本日は、1つのファイルから必要な行だけをピンポイントで切り出して美しいコミットを仕立てるプロの技術を習得します。
- SVNのファイル丸ごとコミットとGitの行単位部分ステージング(Hunk管理)の決定的違いを理解する
git add -p(パッチモード)の対話プロンプトと主要操作コマンド(y,n,s,e,q)を完全習得する- C#クラス内で発生する「本番修正ロジック」と「デバッグ用Console.WriteLine / 一時フラグ」を行単位で峻別する実践フローを身につける
- 変更ブロックが隣接している場合に
s(Split) やe(Edit) を駆使して極限まで細かく選別する技をマスターする - TortoiseGit(TortoiseGitMerge)のGUIを活用し、マウス右クリックで行単位ステージング・破棄を行う直感的手順を習得する
git diff --cachedでコミット直前のステージング状態を100%安全に確認するプロの検証ルーティンを確立する
② 【図解】従来のファイル丸ごとコミットの悲劇 vs git add -p による部分ステージング
まず、従来のSubversion (SVN) や初心者が陥りがちな「ファイル丸ごとコミット」の落とし穴と、Gitの部分ステージングによる解決策を図解で対比してみましょう。
Subversionでは、コミットの最小単位が「ファイル」でした。そのため、1つのファイルの中で作業していると、次のようなジレンマに直面していました。
- デバッグコードの誤コミット: 調査のために入れた
Console.WriteLine("DEBUG: user count=" + count);や、テスト用にコメントアウトした認証処理を戻し忘れ、本番コードに混入してしまう。 - 手動削除による再デバッグの困難: コミット前にデバッグコードをわざわざ手で消し、もし後から再度バグ調査が必要になったら、また同じデバッグコードをゼロから打ち直すという二度手間が発生する。
- 無関係な変更の混入(Dirty Commit): 本番バグを直している最中に、気になったコードのインデントを直したり関係ないコメントを追記してしまい、1つのコミットに関心の異なる変更が混在してレビューが難航する。
これに対してGitは、「ワーキングツリー(ローカル作業フォルダ)」と「インデックス(ステージング領域)」が完全に分離されています。
この構造のおかげで、「ローカルファイル上にはデバッグログや一時的な実験コードを残したまま、本番にコミットしたい行だけをインデックスにコピーする」という魔法のような芸当が可能になります。それをCLIで対話的に実行するコマンドが git add -p(または git add --patch)です!
③ 【図解】git add -p の対話モードとHunk操作コマンド完全図解
git add -p を実行すると、Gitはファイル内の差分をひとかたまりの変更ブロック(Hunk:ハンク)ごとに切り分けて画面に表示し、対話プロンプトで「このブロックをステージングしますか?」と尋ねてきます。
対話プロンプトに表示される Stage this hunk [y,n,q,a,d,s,e,?]? の各コマンドの意味を完璧に整理しておきましょう。
| キー | 名称 | 動作と実務での活用法 |
|---|---|---|
| y | yes(ステージング) | 表示されているHunkをステージング領域に追加します。本番修正コードのブロックで押します。 |
| n | no(スキップ) | このHunkをステージングせずスキップします。作業フォルダのファイルは変更されずそのまま残ります(デバッグログ等)。 |
| s | split(さらに分割) | 表示中のHunkの中に「本番修正」と「デバッグログ」が両方含まれている場合、間に未変更行があれば2つ以上の小さなHunkに自動分割します。 |
| e | edit(手動編集) | 変更行が直結していて s で自動分割できない場合、エディタを開いて不要な + 行を削除し、手動でパッチを微調整します。 |
| q | quit(中断・終了) | 途中でステージング処理を終了します。それまでに y を押したHunkはステージングされた状態で保持されます。 |
| ? | help(ヘルプ) | 使用可能な全コマンドの簡単な説明を表示します。 |
④ 【図解】C#現場での実践!デバッグ用Console.WriteLine混入防止フロー
それでは、実際のC#開発現場を想定した具体的なシナリオで git add -p の実践手順を見てみましょう!
💻 実例:OrderService.cs のバグ修正シナリオ
ECサイトの注文処理サービス OrderService.cs において、「割引額が負数になった場合に例外をスローする」というバグ修正を行いました。
しかし開発中、動作確認のために途中で Console.WriteLine による値の出力や、一時的なフラグ変数を書き加えています。
ここで git add OrderService.cs や git commit -am "fix" を実行してしまうと、赤色の一時デバッグログまで本番に混入してしまいます。
そこで、ターミナルで git add -p OrderService.cs を実行します!
たったこれだけです!
これでインデックス(ステージング)にはバグ修正コードだけが登録され、作業フォルダには引き続き Console.WriteLine が残ったままになります。
ステージングを終えたら、いきなりコミットするのではなく、必ず次のコマンドを実行しましょう:
git diff --cached(または git diff --staged)
通常の git diff は「作業フォルダとステージングの差分」を表示しますが、--cached オプションを付けると「ステージング領域と前回のコミットの差分(=今からコミットされる純粋な内容)」だけが表示されます。
ここで余計なデバッグ行や一時コードが含まれていないことを100%確認してから git commit -m "fix: ..." を実行するのが、プロエンジニアの鉄則です。
⑤ 【図解】TortoiseGitで行単位・ブロック単位にステージングする視覚的GUI操作
「黒い画面(CLI)での対話モードはちょっと敷居が高い……」「左右のカラー差分を見比べながらマウスで安全に選びたい」というWindowsエンジニアの方も安心してください。
エクスプローラー統合の定番GUIツール TortoiseGit を使えば、マウス操作だけでまったく同じ部分ステージングが可能です!
- コミットダイアログを開く: プロジェクトフォルダを右クリックし、「Git コミット(C) -> "ブランチ名"...」を選択します。
- 差分比較(TortoiseGitMerge)を起動: 変更されたC#ファイルをリストからダブルクリックします。左右に差分が表示されたTortoiseGitMergeウィンドウが開きます。
- 除外したい行・ブロックを選択して右クリック:
- 変更を破棄して完全に元に戻したい場合: 該当ブロックを右クリックして「このブロックの変更を取り消す」を選択。
- 作業フォルダに残したままコミット対象から外す場合: コミットダイアログ側の「ステージングを使用」機能(またはパッチ作成)を有効にし、コミット対象とするブロックだけを選択してステージングに移動。
- コミットと確認: コミットダイアログに戻ると、選択したブロックだけがステージング領域に反映されているため、メッセージを入力してコミットします。
📌 まとめ&明日の予告
- SVNとの決定的差: SVNのファイル丸ごとコミットと決別し、Gitのインデックス(ステージング)を活用して行単位(Hunk)で美しく選別コミットせよ!
- 対話モードの3種の神器:
git add -pを実行し、y(採用)、n(除外・ローカル維持)、s(細分化Split)を自在に使いこなせ! - コミット前の絶対防壁: コミット前には必ず
git diff --cachedを叩き、デバッグログや一時フラグが混入していないことを自分の目で100%確かめよ!
次回【Day 29】のテーマは、【git blame & git log -L でC#コードの「犯人・導入理由」を完全特定】です!
「この怪しいif文は一体誰が何のために書いたのか?」「このC#メソッドの過去5年間の変更履歴をピンポイントで追跡したい!」という疑問を瞬時に解決するコード考古学の必須ツール git blame と git log -L の奥義を解説します。お楽しみに!
コメント
コメントを投稿