ブランチ全体をマージすると不要な変更まで取り込まれてしまう。そんなとき、特定のファイルだけを別ブランチから持ってくる方法が役立ちます。
この記事では、git restore(推奨)・git checkout・git cherry-pick・git 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.html が feature ブランチの内容で上書きされ、ステージング(インデックス)にも追加されます。
複数ファイルを一度に取得する
# 複数ファイルをスペース区切りで指定 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 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 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 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 restore --source または git cherry-pick を使います。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

