Gitブランチから特定のファイルをマージする方法


179

2つのgitブランチBranch1とBranch2があり、Branch2のfile.pyをBranch1のfile.pyにマージし、そのファイルだけをマージしたいと思います。

本質的には、branch1のfile.pyで作業したいだけですが、mergeコマンドを利用したいと思っています。これを行う最良の方法は何ですか?



回答:


207

コンテンツがbranch2file.pyからのものであり、branch1には適用されなくなった場合、変更をいくつか選択し、他のものを残す必要があります。完全に制御するには、--patchスイッチを使用してインタラクティブなマージを実行します。

$ git checkout --patch branch2 file.py

のマニュアルページの対話モードのセクションでは、git-add(1)使用されるキーについて説明しています。

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

splitコマンドは特に便利です。


3
どのようにしてパッチを使用し、同時にマージツールを使用できますか?重要なものの代わりに
ガブリエル

@Gabrielリポジトリの作成(git init <dir>)と最終的な破棄()が非常に簡単であるため、パッチファイルとtarballを使用してもGitを使用しましたrm -r <dir>
pdp

105

それ自体はマージではありませんが、別のブランチ上の別のファイルのコンテンツ全体が必要になる場合があります。Jason Rudolphのブログ投稿では、あるブランチから別のブランチにファイルをコピーする簡単な方法を提供しています。次のようにテクニックを適用します。

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

現在file.pybranch1にあります。


91
簡単ですが、実際にはマージではありません。それだけ上書きfile.pyブランチ2にあるもので
グレッグHewgill

ファイルをbranch1からbranch2にマージバックするとどうなりますか?あなたは対立するでしょう!
アミール

これはコミット履歴を保持しますか?
C2H50H

18

mergeコマンドを使用しているかのように、他の現在の回答では実際にファイルを「マージ」しません。(せいぜい手動で差分を選択する必要があります。)共通の祖先からの情報を使用してマージを実際に利用したい場合は、gitの「高度なマージ」セクションにある手順に基づいた手順に従うことができます。参考マニュアル。

このプロトコルでは、「path / to / file.txt」ファイルをorigin / masterからHEADにマージすることを想定しています。必要に応じて変更してください。(リポジトリの最上位ディレクトリにある必要はありませんが、役に立ちます。)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-fileは、フォーマットなどにデフォルトのマージ設定をすべて使用する必要があります。

また、「ours」が作業コピーのバージョンであり、過度に慎重になりたくない場合は、ファイルを直接操作できます。

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

15

すべての変更されているfile.pybranch2、自分のコミットでは、他のファイルへの変更とは別に、?もしそうなら、あなたは単にcherry-pick変更を変えることができます:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

それ以外の場合は、merge個々のパスで動作しません... からgit difffile.py変更branch2git applyそれらへの変更のパッチを作成することもできますbranch1

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

8

次のことが可能stashstash popファイル:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

これは、解決するためにマージの競合を引き起こす必要があるマージの代わりに、branch2 / file.pyの内容でbranch1 / file.pyを上書きします。
plumSemPy

2

branch2の変更のみをマージfile.pyするには、他の変更を削除します。

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

Mergeは他のファイルを見ることさえしません。ツリーが十分に異なる場合は、チェックアウトを「-f」する必要がある場合があります。

これにより、branch1は、branch2の履歴のその時点までのすべてがマージされたかのように見えることに注意してください。上記の最初のチェックアウトのより良いバージョンはおそらく

git checkout -B wip `git merge-base branch1 branch2`

その場合、コミットメッセージもおそらく

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

0

私は同じ状況にあり、2つのブランチで多くのコミットがあるブランチからのファイルをマージしたいと思います。上記の方法やインターネットで見つけた他の方法を試してみましたが、すべてが失敗しました(コミット履歴が複雑なため)。

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

0

私がやったことは少し手作業ですが、私は:

  1. ブランチを正常にマージしました。とのマージを元に戻しましたrevert
  2. すべてのファイルをにチェックアウトしましたHEAD~1。つまり、マージコミットでのファイルの状態です。
  3. このハッカーをコミット履歴から隠すためにコミットをリベースしました。

醜い?はい。覚えやすい?はい。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.