コミットをマージするのではなく、変更を1つのファイルにマージするにはどうすればよいですか?


383

2つのブランチ(AおよびB)があり、ブランチAからの単一のファイルをブランチBからの対応する単一のファイルとマージしたい。


2

27
他の投稿へのほとんどの応答ファイルではなくコミットを選択的にマージする方法に関するものです。これにより、選択した回答が正しくなくなります。質問は未解決のままです。


この答えは行く方法です、IMO。 git diff branch_name > patch git apply patchstackoverflow.com/a/9473543/1091853
blamb

回答:


631

私は同じ問題に出くわしました。正確には、2つのブランチがAありB、ファイルは同じですが、一部のファイルではプログラミングインターフェイスが異なります。これfで、2つのブランチのインターフェースの違いに依存しないfileのメソッドが、branch Bで変更されましたが、変更は両方のブランチで重要です。したがって、私は、ファイルマージする必要がf枝のをBファイルにfブランチのA

私はすべての変更が両方のブランチにコミットしていることを前提とした場合、単純なコマンドは、すでに私のために問題を解決しAB

git checkout A

git checkout --patch B f

最初のコマンドはブランチAに切り替わり、そこでBファイルのバージョンをマージしたいところに行きますf。2番目のコマンドはffof HEADofを使用してファイルにパッチを適用しますB。パッチの単一の部分を受け入れる/破棄することもできます。Bここでコミットを指定する代わりに、である必要はありませんHEAD

コミュニティ編集f上のファイルBがまだ存在しAない場合は、--patchオプションを省略します。それ以外の場合は、「変更なし」になります。メッセージ。


10
これは、ファイルを更新する場合にのみ機能します。ブランチBからブランチAに新しいファイルを追加する場合はどうなりますか?
Umair A. 14

25
@UmairAshraf --patchオプションを削除することで、BからAに新しいファイルを追加できるはずです。
bbak 2014

9
うーん...これを試してみると、「変化なし」というメッセージが表示されますが、明らかに変化があります。OK、私は関連するファイルがあったフォルダーにいなければなりませんでした。編集:これは、stackoverflowで見た問題に対する私のお気に入りの解決策になる可能性があります:-D
bot_bot

2
git checkout --patch B -- fこれを機能させるために使用する必要がありました。
user545424 2015年

8
ファイルに複数の変更(ハンク)があり、それらすべてをステージングする場合はay毎回押すのではなく、インタラクティブフェーズ中にを押すことができることを追加するだけです。または、git checkout B -- f代わりにコマンドを使用してください。
Dmitry Gonchar、2015年

17

これが私がこれらの状況で行うことです。それはkludgeですが、私にとってはうまくいきます。

  1. 作業中のブランチに基づいて別のブランチを作成します。
  2. git pull / git mergeで、コピーするファイルを含むリビジョン(SHA1)をマージします。したがって、これによりすべての変更がマージされますが、このブランチは1つのファイルを取得するためにのみ使用しています。
  3. 競合を修正し、ファイルを調査します。
  4. 作業ブランチをチェックアウト
  5. マージからコミットされたファイルをチェックアウトします。
  6. それをコミットします。

私はパッチを当ててみましたが、私の状況はそれにとって醜いものでした。つまり、次のようになります。

作業ブランチ:A実験ブランチ:B(フォールドインしたい変更があるfile.txtが含まれています。)

git checkout A

Aに基づいて新しいブランチを作成します。

git checkout -b tempAB

BをtempABにマージ

git merge B

マージのsha1ハッシュをコピーします。

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <matthewe@matthewe.com>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

作業ブランチをチェックアウトします。

git checkout A

修正したファイルをチェックアウトします。

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

そして、あなたはそれを持っているべきです。結果をコミットします。


3
したがって、1つのファイルをマージするためだけにこれをすべて行う必要がありますか?ファイルをコピーして他のブランチに貼り付ける方が簡単ではないでしょうか
Robin

1
@Robinはおそらくマージしません。ブランチAとBの間で異なる変更がファイルに保持されるためです。ファイルをコピーすると、作業ブランチAと、Bから取り込んだものの間に含まれていない可能性がある追加の差異が上書きされます。それらのエントリ/編集。たとえば、容疑者AB他の方法でそもそもから転用しています。コピーはそれらの違いを上書きします。
blamb

14

これはgitの内部difftoolを使用します。たぶん少しの作業が必要ですが、単純明快です。

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.

1
--(空の引数ラベル)の使用を明確にするために、git checkout docs:ARGUMENT DISAMBIGUATION say: "use git checkout -- <pathspec>if you want the checkout these path from the index。これは、同じ名前でブランチとファイル/パスの両方を持つことができるためです。このような場合、ブランチまたはパスの両方が存在する場合にチェックアウトする必要があるかどうかを明確にするように求めるのではなく、gitはデフォルトでブランチをチェックアウトすることを選択します。ただし、--前にある場合、gitは代わりにファイル/パスをチェックアウトします。
SherylHohman

8

このアプローチはシンプルで便利であると思いました。別のブランチから特定のファイルを「マージ」する方法

結局のところ、私たちは懸命に努力しています。私たちの親友のgit checkoutは、この仕事に適したツールです。

git checkout source_branch <paths>...

git checkoutに機能ブランチAの名前とマスターブランチに追加する特定のファイルへのパスを指定するだけです。

詳細については記事全体をお読みください


2
これによりファイルは上書きされ、マージされません
Alex G

あなたにとっては、それはあなたが何をしていて何を達成しようとしているのかに依存します。ここでのアイデアは、ブランチBがAのフォークであり、Bの4つのファイルを変更したが、BからAに2つだけマージしたい場合です。通常のマージでは4つすべてがマージされ、ここで選択できます。Bには本質的に新しいファイルが含まれているため、オーバーライドされたように見える場合があります。いくつかの証拠であなたの経験をサポートする必要があります。
Pawel Cioch

上書きすることに同意します。-pそのコマンドでオプションを使用するつもりだったと思います。その後、残念ながら、パッチを変更する前に、チェックアウト元のブランチから迂回したワークツリーファイルの部分を上書きします。
blamb

まあ、アイデアは2009年のものでした。新しいバージョンのgitの動作が異なる可能性があり、-pまたは何か他のものが必要ですが、投稿したときはそれが私のために機能していましたが、ファイルが上書きされていることには気にしていませんでした。最新バージョンは私が必要としていたものでした
Pawel Cioch


3

次のコマンドは、(1)正しいブランチのファイルをマスターと比較し、(2)適用する変更をインタラクティブに尋ねます。

git checkout-パッチマスター


0

編集が拒否されたため、リモートブランチからのマージ変更の処理方法をここに添付します。

間違ったマージの後にこれを行う必要がある場合は、次のようにすることができます。

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.

0

Bが現在のブランチであると仮定します。

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

これはローカルファイルへの変更のみを適用することに注意してください。後でコミットする必要があります。


私にとっては、これが生成されますerror: <file-path>: already exists in working directory
kontur 2017年

現在のディレクトリで特定のファイルまたはファイルパスを指定する必要があります。私が使用していますgit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri

0

古いバージョンのファイルをチェックアウトしてマージし、別の名前で保存してから、2つのファイルに対してマージツールが何であっても実行できます。

例えば。

git show B:src/common/store.ts > /tmp/store.ts (Bはブランチ名/コミット/タグです)

meld src/common/store.ts /tmp/store.ts


0

私はそれをします

git format-patch branch_old..branch_new file

これにより、ファイルのパッチが作成されます。

ターゲットのbranch_oldにパッチを適用します

git am blahblah.patch


安全性を高めるためにパッチを簡単に確認できますか?
XavierStuvw
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.