【Git】特定のファイルだけをマージする方法完全ガイド|git restore・checkout・cherry-pick・コンフリクト解決まで

【Git】特定のファイルだけをマージする方法 Git

ブランチ全体をマージすると不要な変更まで取り込まれてしまう。そんなとき、特定のファイルだけを別ブランチから持ってくる方法が役立ちます。

この記事では、git restore(推奨)git checkoutgit cherry-pickgit merge-file の4つのアプローチを、使い分けの判断基準とともに解説します。

この記事でわかること
git restore で別ブランチのファイルをワークツリーに取得する方法(推奨)
git checkout を使った旧来の方法(Git 2.23未満向け)
・複数ファイル・ディレクトリ全体を指定する方法
git cherry-pick で特定のコミットごと移植する方法
・コンフリクトが発生した場合の解決方法
git merge-file で3-wayマージを行う方法
・どの方法を使うべきかの判断基準
スポンサーリンク

まず現在の状況を確認する

操作前にブランチの状態とファイルの差分を確認しておきましょう。

# 現在のブランチを確認
git branch

# リモートを含む全ブランチを確認
git branch -a

# 別ブランチのファイルの内容を確認(取得前にプレビュー)
git show feature/branch:path/to/file.txt

# 2つのブランチ間でファイルの差分を確認
git diff main feature/branch -- path/to/file.txt

方法1:git restore で別ブランチのファイルを取得する(推奨)

git restore は Git 2.23 で導入されたコマンドで、ファイルの復元・取得に特化しています。現在の推奨コマンドです。

# 構文
git restore --source=<ブランチ名> -- <ファイルパス>

# 例: feature ブランチの app/index.html を現在のブランチに取得
git restore --source=feature -- app/index.html

このコマンドを実行すると、app/index.htmlfeature ブランチの内容で上書きされ、ステージング(インデックス)にも追加されます。

複数ファイルを一度に取得する

# 複数ファイルをスペース区切りで指定
git restore --source=feature -- app/index.html app/style.css

# ワイルドカードを使う
git restore --source=feature -- 'app/*.css'

# ディレクトリ全体を取得
git restore --source=feature -- app/

取得後の確認とコミット

# ステージングに追加されているか確認
git status

# 変更内容を確認
git diff --staged

# 問題なければコミット
git commit -m "feat: feature ブランチから app/index.html を取得"
git restore はワーキングツリーを上書きします
現在のブランチのファイルが上書きされます。未コミットの変更がある場合は、事前に git stash で退避させてから実行してください。

方法2:git checkout で別ブランチのファイルを取得する(Git 2.23未満)

Git 2.23未満ではまだ git restore が使えないため、git checkout を使います。

# 構文
git checkout <ブランチ名> -- <ファイルパス>

# 例: feature ブランチの app/index.html を取得
git checkout feature -- app/index.html

# 複数ファイル
git checkout feature -- app/index.html app/style.css

# ディレクトリ全体
git checkout feature -- app/
git checkout は Git 2.23 以降では git restore・git switch に役割が分割されました
git checkout はブランチ切り替えとファイル取得の両方に使えるため混乱が生じやすく、Git 2.23 からはそれぞれ git switch(ブランチ切り替え)・git restore(ファイル復元)に分離されました。Git バージョンを確認するには git --version を実行してください。

git restore vs git checkout の比較

git restore –source(推奨) git checkout —
利用可能バージョン Git 2.23 以降 全バージョン
意図の明確さ ファイル取得専用で明確 ブランチ切り替えと混同しやすい
構文 git restore --source=branch -- file git checkout branch -- file
結果 ほぼ同じ ほぼ同じ
推奨 ✓ 推奨 非推奨(古いスタイル)

方法3:git cherry-pick で特定のコミットごと移植する

cherry-pick は「特定のコミット」に含まれる変更をそのまま別ブランチに適用します。ファイル単位ではなくコミット単位での移植です。

基本的な手順

# 1. 移植したいコミットのハッシュを確認
git log feature --oneline
# abc1234 Add new login feature
# def5678 Fix header style

# 2. 現在のブランチに cherry-pick で適用
git checkout main  # 適用先に移動
git cherry-pick abc1234
# 複数のコミットを一度に適用
git cherry-pick abc1234 def5678

# コミット範囲を指定(abc1234の次から def5678まで)
git cherry-pick abc1234..def5678

cherry-pick でファイルを絞り込む(コミットしない)

cherry-pick 後に不要なファイルを元に戻すことで、特定のファイルの変更だけを取り込めます。

# -n オプションでコミットせずにステージングのみ適用
git cherry-pick -n abc1234

# 不要なファイルをステージングから外す
git restore --staged path/to/unwanted_file.txt

# ワーキングツリーも元に戻す
git restore path/to/unwanted_file.txt

# 必要なファイルだけでコミット
git commit -m "feat: cherry-pick from feature (specific files only)"

コンフリクトが発生した場合の解決方法

ファイルを取得したり cherry-pick したりした際に、現在のブランチにも同じファイルへの変更があるとコンフリクトが発生します。

コンフリクトの確認

# コンフリクトしているファイルを確認
git status
# both modified: app/index.html  ← コンフリクト中

コンフリクトマーカーの見方

<<<<<<< HEAD
現在のブランチの内容
=======
取り込もうとしているブランチの内容
>>>>>>> feature

<<<<<<< HEAD から ======= が現在のブランチ、======= から >>>>>>> が取り込み元の内容です。どちらを採用するか(または両方を組み合わせるか)を判断してマーカーを削除します。

コンフリクトを解決してコミット

# 1. コンフリクトしているファイルを編集してマーカーを削除
# (エディタで開いて編集)

# 2. 解決済みとしてステージング
git add app/index.html

# 3. コミット(cherry-pick の場合)
git cherry-pick --continue

# 3. コミット(restore/checkout の場合)
git commit -m "merge: app/index.html を feature ブランチから取得(コンフリクト解決済み)"

# 取り込みをキャンセルする場合
git cherry-pick --abort  # cherry-pick の場合
git restore -- app/index.html  # restore の場合(元に戻す)

方法4:git merge-file で3-wayマージを行う

git merge-file は3つのファイル(ベース・現在・変更後)を比較して3-wayマージを行います。通常は git restore や cherry-pick で十分ですが、どちらの変更も活かしたい場合に使います。

# 構文
git merge-file <現在のファイル> <共通の祖先ファイル> <変更後のファイル>

# 実用的な手順:
# 1. 各バージョンをファイルに書き出す
git show HEAD:app/index.html > /tmp/current.html
git show $(git merge-base HEAD feature):app/index.html > /tmp/base.html
git show feature:app/index.html > /tmp/incoming.html

# 2. マージを実行(結果は current.html に書き出される)
git merge-file /tmp/current.html /tmp/base.html /tmp/incoming.html

# 3. 結果を確認してコピー
cat /tmp/current.html
cp /tmp/current.html app/index.html
実務では git merge-file を直接使うことは少なく、VSCode・IntelliJ などのGUI差分ツールで3-wayマージを行うのが一般的です。コンフリクト解決に特化したGUIの方が可読性が高く安全です。

どの方法を使うべきか:判断基準

状況 推奨方法 理由
別ブランチの最新ファイルをそのまま取得したい git restore --source シンプルで安全
特定のコミットの変更をまるごと取り込みたい git cherry-pick コミット履歴も一緒に移植される
コミットの変更の一部だけ取り込みたい git cherry-pick -n + 不要ファイルをリストア 柔軟な選択が可能
旧バージョンのGit(2.23未満)を使っている git checkout -- ファイル restore が使えない場合
両方の変更を手動でマージしたい git merge-file 細かい3-wayマージが可能
注意:git restore / git checkout はファイルの「変更履歴」を取り込みません
ファイルの内容をそのまま上書きするため、コミットログ上は「現在のブランチでの変更」として記録されます。変更履歴ごと持ってくる必要がある場合は git cherry-pick を使いましょう。

よくある実践シナリオ

シナリオ1:feature ブランチで直した bugfix を main にだけ反映したい

# feature ブランチで修正したコミットハッシュを確認
git log feature --oneline | head -10
# a1b2c3d Fix null pointer exception in auth.js

# main ブランチに移動して cherry-pick
git checkout main
git cherry-pick a1b2c3d

シナリオ2:develop の設定ファイルだけを staging に持っていきたい

# staging ブランチに移動
git checkout staging

# develop ブランチから設定ファイルだけを取得
git restore --source=develop -- config/app.yaml config/database.yaml

# 確認
git diff --staged

# コミット
git commit -m "chore: develop の設定ファイルを staging に反映"

シナリオ3:間違えて別ブランチで作ったファイルを正しいブランチに移す

# 間違えて old_branch に作ってしまったファイルを new_branch に持っていく
git checkout new_branch
git restore --source=old_branch -- path/to/newfile.js

# old_branch からそのファイルを削除(必要に応じて)
git checkout old_branch
git rm path/to/newfile.js
git commit -m "refactor: newfile.js を正しいブランチに移動"

よくあるトラブルと解決法

ケース1:pathspec エラーが出る

# エラー例
# error: pathspec 'app/index.html' did not match any file(s)

# 原因: ファイルパスが間違っている
# 確認: ブランチ内のファイル一覧を表示
git ls-tree -r feature --name-only | grep index

# 原因: ブランチ名が間違っている
git branch -a  # ブランチ一覧を確認

ケース2:取得後にコミットしたら他のファイルの変更も入ってしまった

# git restore した後に git status で確認してからコミットする
git status

# 特定のファイルだけをステージングしてコミット
git add app/index.html
git commit -m "..."
# (他の変更はステージングされていないのでコミットされない)

ケース3:取得した内容を元に戻したい

# コミット前なら git restore で元に戻せる
git restore -- app/index.html

# ステージングから外す
git restore --staged app/index.html

# コミット後は git revert か git reset
git revert HEAD  # 新しいコミットで取り消す(安全)
git reset HEAD~1  # コミットを取り消す(ローカルのみ)

よくある質問

git merge でファイルを指定することはできますか?
git merge コマンド自体にファイル指定の機能はありません。特定のファイルだけ取り込む場合は git restore --source または git cherry-pick を使います。
git restore でファイルを取得するとコミット履歴は変わりますか?
ファイルの内容が上書きされるだけで、コミット履歴は変わりません。git restore 後にコミットすると「現在のブランチで変更した」というコミットが作成されます。変更履歴ごと持ってくる必要がある場合は git cherry-pick を使ってください。
リモートブランチのファイルを取得できますか?
できます。まず git fetch でリモートブランチを取得してから、git restore --source=origin/feature -- file.txt のように origin/ブランチ名 で指定します。
取得したファイルのコンテンツが古いバージョンで上書きされてしまった
git restore は取得元ブランチの最新の内容でそのまま上書きします。事前に git show branch:file.txt で内容を確認してから実行することを推奨します。誤って上書きした場合は git restore -- file.txt(HEADの内容に戻す)または git checkout HEAD -- file.txt で元に戻せます。
削除されたファイルを別ブランチから取り込むには?
ファイルが削除された状態のブランチから取り込む場合、そのファイルは存在しないため git restore --source は使えません。削除前のコミットハッシュを git log --diff-filter=D -- path/to/file で調べ、git restore --source=<コミットハッシュ>^ -- path/to/file で取り込めます。

まとめ

やりたいこと コマンド 注意点
別ブランチのファイルを取得(推奨) git restore --source=branch -- file Git 2.23以降
別ブランチのファイルを取得(旧方式) git checkout branch -- file Git全バージョン対応
複数ファイルを指定 スペース区切りまたはワイルドカード app/*.css など
ディレクトリ全体を取得 git restore --source=branch -- dir/ サブディレクトリも含む
特定コミットを移植 git cherry-pick <hash> コミット履歴も一緒に移植
コミットの一部だけ取込 git cherry-pick -n + 不要ファイルをリストア 柔軟な選択が可能
コンフリクト解決後に続ける git cherry-pick --continue ファイル編集→git add が先
操作をキャンセル git cherry-pick --abort 元の状態に戻る
まとめ:使い分けの指針
最新内容をそのまま取得git restore --source=branch -- file
コミット履歴ごと移植git cherry-pick <hash>
旧バージョン(Git 2.23未満)git checkout branch -- file

あわせて読みたい