【脱・全部コミット】Gitで部分的にパッチを当てる(ステージング)賢い方法
Staging patches with git add (2024)
Staging patches with git add (2024)
Gitを使って作業している際、「変更したコードのうち、この部分だけをコミットしたい!」と思ったことはありませんか?そんな時に役立つのがパッチ形式でのステージングです。git add -p コマンドを使えば、インタラクティブに変更箇所を選択してステージングできるため、コミット単位を細かく整理したい時に非常に便利です。クリーンなコミット履歴を保つために、ぜひマスターしておきましょう。
大きな変更セットから特定のハンクだけを抜き出したいなら、grepdiffとこの関数がかなり便利だよ:
#!/bin/bash
# .bashrcか何かにいれておいて。
function git-add-regex {
git diff -U0 | grepdiff -E "$1" --output-matching=hunk | git apply --cached --unidiff-zero
}
https://gist.github.com/smuuf/76bde33d65b3dbbc2411e8519f3e6c... (https://gist.github.com/smuuf/76bde33d65b3dbbc2411e8519f3e6c18)
ハンクの分割って面倒くさいよね。行単位で分割できたらいいのに、それができれば最高の機能になると思う。
めちゃくちゃ便利だし、VS Codeのマージペインなら簡単にできるよ。
新規コミットするファイルの場合、とりあえずこれでファイルを追加しておいて
git add . -N
それからgit add -pのワークフローでテキスト自体を確認するのがいいよ。
Magitならハンク単位でも、行を選択(Emacsでいう「リージョン」)してでもステージング/アンステージングができるよ。ファイルまるごとの時以外は、gitコマンドラインでステージングするのは避けてるな。
追伸:jj向けのMagit風ツールであるMajutsuでも同じことができるよ。
自分はいつもgit add -iを使ってる。一つ上のレベルって感じかな。TUIは日常的なタスクに対して直感的だし、コードの一部や行単位のステージングもこなせるよ。
もしgit add -pを使ってコミットをステージングしていないなら損してるよ。
jujutsuに乗り換えてからは、この機能が恋しいなんてこれっぽっちも思わないね。
jjはアプローチが逆なんだ。常にステージングされた状態で、切り分けたい時はいつでもsplitするだけ。
(もちろん、ステージングされた変更はリビジョンとして保存されるから、いつでも前のステージング状態に戻せるよ)。
add -pで一番困るのが、うっかり追加したり拒否したりしたパッチの修正だよね。不要なものを次々と飛ばして、最後に「あれ、さっきのハンクは必要だった」って気づくことがよくある。でもそこに戻れないから、やり直してまた飛ばしすぎないように慎重に作業しなきゃいけない。
jとkのショートカットで、まだ見てないハンクだけじゃなく、既に追加/拒否したハンクにも戻れるようになるといいんだけど。ステージングしたくない変更が大量にある時に、リスト内で「現在地を見失う」のは本当に最悪だよ。
このワークフローで一番最悪なのは、最後にうっかりgit commit -amを実行して、せっかく丁寧にステージングしたものを台無しにすることだね。
ファイルの一部だけコミットする機能は便利だけど、テストされていないコードのコミットを助長している気がする。Fossil scmに同等の機能がないのは、まさにこの問題があるからだよ。