Git Patch & Git Apply: コミットログを汚さずにコードを「爆速」で共有する方法

Git tutorial - IT technology blog
Git tutorial - IT technology blog

「ゴミブランチ」問題とプッシュ・プルの恐怖

開発に没頭している最中、チームのメンバーから「ここのロジックを共有して。自分の環境が古くてテストできないんだ」とメッセージが届くことがあります。もしその時、中途半端なコードや構文エラーが含まれたまま共通ブランチにコミットしてプッシュしてしまったら、Gitの履歴は「temp commit」や「fix bug 1, 2, 3」といった無意味なコミットで埋め尽くされ、戦場のような惨状になってしまいます。これは非常にかっこ悪く、プロフェッショナルとは言えません。

私はかつて、間違ったブランチに強制プッシュ(force push)してコードを失うという苦い経験をしました。それ以来、push --forceや未完成のものをサーバーに上げることに非常に抵抗を感じるようになりました。実際のプロジェクトでGit Patchをワークフローに取り入れてから半年、これがスムーズなチームワーク、特に迅速なレビューやリモートリポジトリを経由しないマシン間でのコード転送に欠かせない「奥義」であることに気づきました。

なぜ作業が終わる前に「プッシュ」を避けるべきなのか?

実のところ、Gitは履歴管理において非常に「厳格」です。プッシュするたびに、プロジェクトのタイムラインに消えない足跡を残すことになります。CI/CDが導入されているプロジェクトでは、むやみにプッシュすると無駄なパイプラインを何十回も実行させることになり、リソースの無駄遣いにもつながります。

  • コミットログが汚れる その場しのぎのコミットは、後でgit logを見る人にとっての悪夢になります。
  • 無意味なコンフリクト 中途半端なコードを上げると、同僚がプルした際に不必要な不具合を引き起こし、修正に余計な時間を取らせてしまいます。
  • 機密情報の露出: デバッグ中に一時的なconsole.logや環境変数を追加しているかもしれません。それらがGitHub上に公開されるのは絶対に避けたいはずです。
  • ネットワーク遅延: 回線の調子が悪い時や会社のVPNが極端に遅い時、数行のコードを送るためだけにプッシュやプルを待つのは苦行でしかありません。

よくある「場当たり的」な対処法

Patchを知る前、エンジニアたちはいくつかの面倒な方法でやりくりしていました:

  1. Slackでコピペ: 短いコードなら使えますが、変更が10個のファイルにまたがっている場合はお手上げです。さらに、コードのフォーマットが崩れやすいという欠点もあります。
  2. フォルダを圧縮して送信: node_modulesを含んだ圧縮ファイルは200MBにもなることがありますが、実際の変更は数KB程度です。非常に非効率です。
  3. Git Stashを使う git stashは自分のマシン内だけで有効なローカルな機能です。そのスタッシュを同僚のマシンに直接「運ぶ」簡単な方法はありません。

Git Patch — プロフェッショナルなワークフローのための必殺技

簡単に言うと、Patchファイルはファイル間のすべての変更点(diff)を含む「総譜」のようなものです。非常に軽量で読みやすく、Gitが最も好むネイティブな形式です。

方法1:Git Diff(未コミットのコードに最適)

まだ何もコミットしておらず、ファイルを修正した直後にすぐ送りたい場合は、git diffを使用します。

# 現在の変更からパッチファイルを作成
git diff > my_changes.patch

# 新規作成したファイル(untracked files)も含める
git add -N . 
git diff > full_changes.patch

このmy_changes.patchファイルは、通常わずか数KBです。TelegramやSlackで一瞬で送ることができます。受け取り側はコマンド一つで、あなたのコードをそのまま再現できます。

方法2:Git Format-Patch(コミット履歴を保持する)

ローカルでいくつかコミット済みで、作成者やコミット日時などの情報も共有したい場合にこれを使います。format-patchはコミットごとに個別の.patchファイルを出力します。

# 直近のコミットのパッチを作成
git format-patch -1 HEAD

# 2つのブランチ間の差分のパッチを作成
git format-patch main..feature-branch

結果として、0001-fix-bug-logic.patchのような名前のファイルが生成されます。このファイルにはフルメタデータが含まれているため、誰がそのコードを書いたのかを正確に伝えることができる「高品質」なパッチです。

プロジェクトにパッチを適用する方法

パッチファイルの作成方法に応じて、コードベースに取り込む方法も異なります。

Git Apply を使う(git diff から作成されたファイル用)

このコマンドは現在のソースコードに変更を適用しますが、新しいコミットは作成しません。

# 適用前にコンフリクトがないか確認
git apply --check my_changes.patch

# 問題なければ適用を実行
git apply my_changes.patch

もし現在のコードと差が大きすぎてエラーが出る場合は、--rejectを使用してください。Gitはエラーのない部分だけを適用し、コンフリクトした部分は手動修正用に.rejファイルとして書き出します。

Git AM を使う(format-patch から作成されたファイル用)

AMは「Apply Mailbox」の略です。このコマンドは非常に強力で、元のマシンと同じ情報を保持したまま自動的にコミットまで作成してくれます。

# パッチを適用し、自動でコミットを作成
git am < 0001-fix-bug-logic.patch

# もしコンフリクトが発生した場合:
# ファイルを修正した後に以下を実行:
git add .
git am --continue

失敗を避けるための「血の滲むような」教訓

半年間Patchを使い続けた結果、スムーズに運用するための注意点をいくつかまとめました:

  • バイナリファイルを忘れない: パッチはデフォルトではテキストのみを扱います。画像や圧縮ファイルを変更した場合は、パッチ作成時に--binaryフラグを忘れずに追加してください。
  • 常に事前に –check を実行する: いきなり適用してはいけません。チェックには1秒もかかりませんが、何時間もの手戻りを防いでくれます。
  • ホットフィックスの救世主: 本番サーバーでバグが発生した際、Gitへの直接アクセス権限がなかったことがありました。ローカルでパッチを作成し、運用チームに送ってサーバーに直接適用してもらったところ、パイプラインのビルドを15分待つ代わりに、わずか2分で修正が完了しました。
  • オフラインでのコードレビュー: Web上のインターフェースで見る代わりに、IDEでパッチファイルを読むのが好きです。これにより、すぐにコードを動かしてロジックを検証できるからです。

結論として、単にコードを素早く転送したいだけならgit diffが手軽です。一方、各コミットの価値を保ちたいならgit format-patchが最適です。今日からぜひ試してみてください。ワークフローがよりプロフェッショナルで柔軟になることは間違いありません。

Share: