エンジニア諸君、日々Gitのコンフリクト地獄と戦っているだろうか。
「マージしたら大量のファイルが衝突した…」「この修正だけを取り込みたいのに、ブランチごと持ってくると余計な変更まで入ってしまう」。そんな経験、一度や二度ではないはずだ。
今日伝授するのは、Gitを「ただのバージョン管理ツール」から「精密な手術メス」に変える禁断のコマンド、`git merge-file` だ。これをマスターすれば、君はもうマージの爆風に巻き込まれることはなくなる。
—
なぜ「git merge-file」なのか?
通常、我々は `git merge` を使って「ブランチ単位」で歴史を統合する。しかし、現場では「Aブランチにある特定の関数の修正だけを、今作業中のBブランチに持ってきたい」という状況が頻発する。
普通なら `cherry-pick` を検討するが、それだとコミット単位の変更しか選べない。`git merge-file` は、ファイルの中身を直接、しかも3つのファイル(共通祖先・現在・変更先)を突き合わせて強制的にマージするための低レイヤーコマンドだ。
1. 準備:環境の確認
Gitをインストールしているなら、`git merge-file` は既に君の武器庫に入っている。特別なインストールは不要だ。ターミナルで以下を叩いてみよう。
git merge-file –help
これでマニュアルが表示されれば準備完了。世界最高峰の外科手術の始まりだ。
2. HelloWorld的演習:衝突を「狙って」解決する
まずは仕組みを理解しよう。以下のファイルを用意して、実験してみる。
- `base.txt`: 「共通の親」
- `mine.txt`: 「自分の作業分」
- `yours.txt`: 「取り込みたい変更分」
準備スクリプト:
echo “Hello World” > base.txt
echo “Hello Git” > mine.txt
echo “Hello World!” > yours.txt
ここで `mine.txt` に `yours.txt` の修正を適用したいとする。普通にマージすると衝突するはずだ。
実行コマンド:
構文: git merge-file [現在のファイル] [共通祖先] [取り込み元]
git merge-file mine.txt base.txt yours.txt
何が起きたか:
`mine.txt` を開いてみてほしい。中身はこうなっているはずだ。
<<<<<<< mine.txt Hello Git ======= Hello World! >>>>>>> yours.txt
そう、Gitが「ここが衝突したぞ」とマーカーを挿入し、ファイル全体を破壊することなく、該当箇所だけをマージ可能な状態にした。 これが `git merge-file` の真髄だ。
—
3. 実践:現場で震えるほど役立つワークフロー
実際の開発でどう使うか。例えば、「ブランチAの `api_client.py` の特定のメソッドだけ、今のブランチに取り込みたい」というケース。
ステップ1:必要なファイルだけを一時的に取り出す
`git show` を使って、特定のブランチの特定時点のファイルを直接引っ張り出す。
ブランチ feature-A の api_client.py を feature-B に持ってきたい
git show feature-A:./path/to/api_client.py > api_client_target.py
ステップ2:共通祖先を見つける
マージには「共通の祖先(マージベース)」が必須だ。Gitは親切にこれを教えてくれる。
git merge-base main feature-A
出力されたハッシュ値(例: abc1234)を控える
git show abc1234:./path/to/api_client.py > api_client_base.py
ステップ3:局所マージを敢行する
現在の作業中ファイルと、今取り出した二つのファイルを突き合わせる。
git merge-file ./path/to/api_client.py api_client_base.py api_client_target.py
これで、作業中の `api_client.py` に、特定の修正だけがマージされる。もし衝突があればマーカーが入るから、そこだけエディタで修正すればいい。終わったら不要な一時ファイルを消すだけだ。
—
達人からのアドバイス
このテクニックの最大の利点は、「歴史を汚さない」ことだ。
`merge` コマンドで強引にマージすると、関係ない変更や古いコミットが混入し、ログがスパゲッティ化する。しかし `git merge-file` を使えば、必要な変更だけを「現在の作業」として取り込めるため、コミット履歴が驚くほどクリーンに保たれる。
注意点:
このコマンドは「ファイル」に対して行われる。プロジェクト全体のリファクタリング中には使わないでくれ。あくまで「特定のロジックの移植」や「設定ファイルの微調整」など、外科手術が必要な局面でのみ使用すること。
さあ、恐れることはない。Gitは単なるツールだ。君がその挙動を支配し、コードの歴史を意のままに操るんだ。
次にコンフリクトに遭遇した時、君は「困った」ではなく「メスを入れるか」と微笑むことだろう。
健闘を祈る。