プログラミング
Git add -p を使ったパッチのステージング
Staging patches with Git add -p (simonholywell.com)
要約
Git add -p コマンドは、ファイル全体ではなく、変更された部分(hunk)ごとにインタラクティブにステージングできる強力な機能です。これにより、コミット内容を細かくレビューし、誤りを早期に発見したり、関連する変更を別々のコミットにまとめたりすることが可能になります。この機能は、日常的なGitワークフローにおいて、よりクリーンで整理されたコミット履歴を作成するために非常に役立ちます。
全文翻訳
はじめに
もしあなたがまだgit add -pを使ってコミットをステージングしていないなら、それは損をしています。この機能を使うと、ファイル全体またはその一部だけをインタラクティブにステージングでき、gitコミットプロセスに対するより大きな制御が可能になります。
なぜこれを使いたいのか?
私のワークフローでgit add -pを使う理由をいくつか挙げます。主に、ステージングしながら変更を確認できるため、しばしば間違いを見つけることができます。ステージング中に変更を確認することで、初期のコーディングやコンテンツ作成中に見逃された可能性のあるバグ、タイプミス、その他の問題を発見できます。
さらに別の利点もあります。それは、ファイルの一部だけをステージングできることです。Gitは奇妙なことに、これらの部分を「hunk」と呼びますので、以降はこの用語を使用します。
この機能は、多くの変更を行ったが、それらを異なるコミットにグループ化したい場合に非常に役立ちます。ファイル内の異なる部分にわたるいくつかの関連する変更を行ったと想像してください。git add -pを使用すると、これらの変更を選択的にステージングし、よりクリーンで整理されたコミットを保証できます。
ファイルの一部をステージングする
ここでは、diffを表示し、「このhunkをステージングしますか?」と尋ねるインターフェースの例を示します。
```
diff --git a/main.mts b/main.mts
index e1132f2..8f7c279 100644
--- a/main.mts
+++ b/main.mts
@@ -1,2 +1,4 @@
export const add = (a, b) => a + b
+export const div = (a, b) => a / b
export const sum = (xs) => xs.reduce((acc, x) => sum(acc, x))
+export const avg = (xs) => div(sum(xs), xs.length)
```
(1/1) Stage this hunk [y,n,q,a,d,s,e,?]?
最も簡単な形式では、yを入力してそのdiffをコミットの準備ができた状態にステージングするか、nを入力してステージングしないことができます。この例では、avg関数をコミットする準備はできていませんが、divをプッシュアップしたいので、hunkをより小さなhunkに分割するためにsを入力します。Gitは次にこれを尋ねてきます。
```
Split into 2 hunks.
@@ -1,2 +1,3 @@
export const add = (a, b) => a + b
+export const div = (a, b) => a / b
export const sum = (xs) => xs.reduce((acc, x) => sum(acc, x))
```
(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?
そこで、yを入力してそのhunkをステージングし、Gitは次のhunkで応答します。
```
@@ -2 +3,2 @@
export const sum = (xs) => xs.reduce((acc, x) => sum(acc, x))
+export const avg = (xs) => div(sum(xs), xs.length)
```
(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]?
div関数だけをコミットしたいことを覚えていて、インタラクティブなhunkステージングを終了するためにqを入力します。
hunkステージングと対話した後、コマンドプロンプトに戻ります。そこから、git commitまたはその他の必要なコマンドに進むことができます。
機能したか確認する
git statusを実行してステージングされたファイルを確認すると、ファイル(main.mts)が両方のセクション(コミット対象、ステージングされていない)に表示されていることがわかります。これは、ファイルの一部だけをステージングしたためであり、まさに望んでいたことです!
```
On branch main
Your branch is ahead of 'origin/main' by 1 commit. (use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: main.mts
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: main.mts
```
ファイルの一部だけを選択的にステージングすることで、次のコミットのために1つのhunk、つまりパッチを正常に準備しました。
その他のオプション
潜在的な応答のリスト([y,n,q,a,d,s,e,?])は短縮されていますが、?を入力してヘルプドキュメントを取得することで、拡張情報を得ることができます。
インタラクティブなhunkステージング中に使用できる応答オプションを、gitのドキュメントから抜粋して以下に示します。以前見たリストよりも多くのオプションがあることに気づくでしょう。
- y: このhunkをステージングする
- n: このhunkをステージングしない
- a: このhunkとファイル内の残りのすべてのhunkをステージングする
- d: このhunkもファイル内の残りのhunkもステージングしない
- g: 移動するhunkを選択する
- /: 指定された正規表現に一致するhunkを検索する
- j: このhunkは未決定のままにし、次の未決定のhunkを表示する
- J: このhunkは未決定のままにし、次のhunkを表示する
- k: このhunkは未決定のままにし、前の未決定のhunkを表示する
- K: このhunkは未決定のままにし、前のhunkを表示する
- s: 現在のhunkをより小さなhunkに分割する
- e: 現在のhunkを手動で編集する
- ?: ヘルプを表示する
使用しない場合
私はコミットするたびに、ほぼ毎日git add -pを使用しています。使用しない場合は2つの状況があります。
- 初めてコミットする新規作成ファイルの場合 - ファイルが新規作成された場合、比較対象となる以前のバージョンがないため、git add -pは承認のためにdiffを表示できません。
- ごくまれに、ディレクトリ全体をコミットしたい場合で、その内容に自信がある場合は、通常標準的なアプローチを選択します。しかし、そのようなエッジケースでも、より細かい制御のためにgit add -pを使用することがよくあります。
結論
git add -pをワークフローに組み込むことで、gitとコミットのプロセスを合理化できます。誇張なしに、変更セットをgitにコミットする必要があるたびに、ほぼ毎回このテクニックを使用しています。これにより、ステージングしながらコードを簡単にレビューでき、各コミットに何が含まれるかを正確に制御できます。