Gitの別のブランチから選択的にマージまたは変更を選択する方法は?


1450

私は2つの並行しているが、現在実験的である開発ブランチを持つ新しいプロジェクトでgitを使用しています:

  • master:既存のコードベースのインポートと、私が一般的に確信しているいくつかのモッド
  • exp1:実験ブランチ#1
  • exp2:実験ブランチ#2

exp1exp22つの非常に異なるアーキテクチャアプローチを表しています。私がさらに進むまで、どれが(もしあれば)機能するかを知る方法がありません。1つのブランチで作業を進めると、他のブランチで役立つ編集が時々あり、それらだけをマージしたいと思います。

ある開発ブランチから別のブランチに選択的な変更をマージし、他のすべてを残しておくための最良の方法は何ですか?

私が検討したアプローチ:

  1. git merge --no-commit その後、ブランチ間で共通にしたくない大量の編集を手動でステージング解除します。

  2. 共通ファイルを一時ディレクトリにgit checkout手動でコピーした後、他のブランチに移動し、一時ディレクトリから作業ツリーにさらに手動でコピーします。

  3. 上記のバリエーション。ここではexpブランチを放棄し、実験のために2つの追加ローカルリポジトリを使用します。これにより、ファイルの手動コピーがはるかに簡単になります。

これらの3つのアプローチはすべて退屈でエラーが発生しやすいようです。より良いアプローチがあることを願っています。git-mergeより選択的になるフィルターパスパラメーターのようなもの。


5
実験的なブランチの変更が別々のコミットでうまく整理されている場合は、選択的ファイルでなく選択的コミットをマージすることを検討することをお勧めします。以下の回答のほとんどは、これが事実であると想定しています。
akaihola

2
git merge -s ours --no-commitこれに続くの組み合わせは、これgit read-treeに対する良い解決策ではないでしょうか?stackoverflow.com/questions/1214906/…を
VonC

34
:より最近の質問には、1行、よく書かれた答えがあるstackoverflow.com/questions/10784523/...
brahn

特定のファイルのみをマージするには、このブログをチェックしてくださいjasonrudolph.com/blog/2009/02/25/…
アッシュートッシュChamoli

回答:


475

1つのブランチから個別のコミットを取得するには、cherry-pickコマンドを使用します。

必要な変更が個別のコミットにない場合は、ここに示す方法を使用して、コミットを個別のコミット分割します。大まかに言えば、git rebase -i元のコミットを編集してから、git reset HEAD^選択的に変更を元に戻し、次にgit commitそのビットを履歴内の新しいコミットとしてコミットするために使用します。

Red Hat Magazineには、別の方法があり、そこで使用しgit add --patchたり、場合によってはgit add --interactiveは、個々のファイル(「スプリット」のため、そのページ内検索)への別の変更を分割したい場合は、塊の部分だけを追加することができます。

変更を分割した後、必要なものだけを選択できます。


14
私の理解から、これは投票の多い回答よりも不必要に複雑です。
アレクサンダーバード

54
これは厳密には正解です。正解は「複雑」に表示されます。---投票数が多い方の回答は、迅速で汚い「トリックを実行する」という回答であり、ほとんどの人にとってそれがすべてです(:
Jacob

3
@akaihola:HEAD ^は正しいです。man git-rev-parseを参照してください:リビジョンパラメーターのサフィックス^は、そのコミットオブジェクトの最初の親を意味します。プレフィックス^表記は、コミットから到達可能なコミットを除外するために使用されます。
タイラーリック

13
私はそれらすべての中で最もクリーンで複雑ではないように見える別のアプローチを共有したいと思いました:jasonrudolph.com/blog/2009/02/25/…完全なシンプルさと素晴らしい
superuseroi 14

14
どのアプローチが「正しい」かについての議論に混乱していますか?ファイルとコミットの違いを考慮してください(下部の備考を参照)。OPはFILESのマージを望んでおり、COMMITSについては言及していません。投票数の多い回答はファイルに固有です。受け入れられた回答は、コミットに固有のチェリーピックを使用しています。チェリーピックはコミットを選択的にマージするための鍵となるかもしれませんが、あるブランチから別のブランチにファイルを移動することは非常に困難です。コミットはgitの強みの中心ですが、ファイルがまだ役割を持っていることを忘れないでください!
Kay V

970

私は上記のあなたが述べたのとまったく同じ問題を抱えていました。しかし、私は答えを説明することでこれをより明確に見つけました。

概要:

  • マージしたいブランチからパスをチェックアウトし、

    $ git checkout source_branch -- <paths>...
    

    ヒント:--リンクされた投稿で見られるようなものなしでも機能します。

  • または、選択的にハンクをマージする

    $ git checkout -p source_branch -- <paths>...
    

    または、リセットを使用して、オプション-pで追加します。

    $ git reset <paths>...
    $ git add -p <paths>...
    
  • 最後にコミット

    $ git commit -m "'Merge' these changes"
    

9
Bart Jのリンクされた記事が最良のアプローチです。明確でシンプルな1つのコマンド。私がこれから使用するものです。:)
ピストス

256
これは本当のマージではありません。コミットではなくファイルで変更を選択すると、既存のコミット情報(作成者、メッセージ)が失われます。確かに、一部のファイルのすべての変更をマージしたい場合や、すべてのコミットをやり直さなければならない場合は、これで十分です。ただし、マージする変更と破棄する変更の両方がファイルに含まれている場合は、他の回答で提供されている方法の1つが適切に機能します。
akaihola

10
@mykhalおよびその他:これにより、インデックス内のファイルが自動的にステージングされるため、チェックアウトfoo.cgit reset HEAD foo.cた場合は、そのファイルのステージングを解除して、diffできます。私はそれを試して、これに対する答えを探すためにここに戻ってきた後にこれを見つけました
michiakig

12
使用できる変更を確認するには:git diff --cached
OderWat

9
この回答に よると、git checkout -p <revision> -- <path>あなたが説明した最初の3つのコマンドを発行するのと同じになります:)
7hi4g0 '22

338

あるブランチから別のブランチにファイルを選択的にマージするには、次を実行します。

git merge --no-ff --no-commit branchX

どこ branchXあなたは現在のブランチにマージしたいからブランチです。

--no-commitオプションは、Gitによってマージされたファイルを実際にコミットせずにステージングします。これにより、マージしたファイルを必要に応じて変更し、自分でコミットする機会が与えられます。

ファイルをマージする方法に応じて、4つのケースがあります。

1)真のマージが必要です。

この場合、Gitが自動的にマージした方法でマージされたファイルを受け入れ、それらをコミットします。

2)マージしたくないファイルがいくつかあります。

たとえば、現在のブランチのバージョンを保持し、マージ元のブランチのバージョンを無視したいとします。

現在のブランチのバージョンを選択するには、次を実行:

git checkout HEAD file1

これによりfile1、現在のブランチにあるのバージョンが取得file1され、Gitによって自動マージされたものが上書きされます。

3)BranchXのバージョンが必要な場合(真のマージではない場合)。

実行:

git checkout branchX file1

これによりfile1、in のバージョンが取得され、Gitによって自動マージされたものがbranchX上書きfile1されます。

4)最後のケースは、で特定のマージのみを選択する場合ですfile1

この場合、変更されたファイルをfile1直接編集して、必要なバージョンに更新できます。file1コミットできます。

Gitがファイルを自動的にマージできない場合、Gitはファイルを「unmerged」として報告し、競合を手動で解決する必要があるコピーを生成します。



例でさらに説明するためbranchXに、現在のブランチにマージしたいとしましょう:

git merge --no-ff --no-commit branchX

次に、git statusコマンドを実行して、変更されたファイルのステータスを表示します。

例えば:

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#

どこでfile1file2file3、、、は、gitが正常に自動マージしたファイルです。

これが意味することはmasterbranchX、すべてのこれら3つのファイルが競合することなく、一緒に組み合わされているため。

を実行すると、マージがどのように行われたかを確認できgit diff --cachedます。

git diff --cached file1
git diff --cached file2
git diff --cached file3

マージが望ましくない場合は、次のことができます。

  1. ファイルを直接編集する
  2. セーブ
  3. git commit

マージせずfile1、現在のブランチのバージョンを保持したい場合

走る

git checkout HEAD file1

マージfile2したくなくて、バージョンを入れたいだけの場合branchX

走る

git checkout branchX file2

file3自動的にマージしたい場合は、何もしないでください。

この時点で、Gitはすでにそれをマージしています。


file4上記はGitによるマージの失敗です。これは、同じ行で発生する両方の分岐に変更があることを意味します。ここで競合を手動で解決する必要があります。マージしたファイルは、ファイルを直接編集するか、ブランチにしたいバージョンのチェックアウトコマンドを実行して破棄できますfile4


最後に、を忘れないでくださいgit commit


10
注意:ただし、これgit merge --no-commit branchXが早送りの場合、ポインタは更新されるため、
-no

16
@cfi --no-ffその振る舞いを防ぐために追加するのはどうですか?
エドゥアルドコスタ

5
Eduardoの「--no-ff」オプションでこの回答を更新することをお勧めします。マージを早送りするためだけに、全体を読み通しました(他の点では優れていました)。
Funktr0n 2014年

7
このソリューションは、最高の結果と柔軟性を提供します。
チアゴマセド2014

20
投票数が最も多い回答とは異なり、このソリューションはマージ履歴を保持しました。ブランチ全体で部分的なコミットを前後に織り交ぜているため、これは私にとって重要です。私は他の提案された解決策のすべてを試したわけではないので、おそらくそれらのいくつかはこれも行います。
ws_e_c421 2014年

107

上記のアプローチは好きではありません。チェリーピックの使用は、単一の変更を選択するのに最適ですが、一部の悪い変更を除いてすべての変更を取り込もうとすると、苦痛です。これが私のアプローチです。

--interactivegit mergeに渡すことができる引数はありません。

ここに代替があります:

ブランチの「機能」にいくつかの変更があり、それらのすべてではなく一部をずさんな方法で「マスター」に持ち込みたい(つまり、それぞれをチェリーピックしてコミットしたくない)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

だからそれをシェルスクリプトでラップし、マスターを$ toに変更し、機能を$ fromに変更すれば、準備完了です。

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp

私はフォーマットを修正しました-これは、コミットを選択したい場合、かなり良い方法です
1800 INFORMATION

私は今このテクニックを使っていますが、それは本当にうまくいったようです。
dylanfm 2010

4
リベースが失敗した場合にユーザーが必要に応じてetc を呼び出せるようgit rebase -i $togit rebase -i $to || $SHELL、に変更することもできgit --skipます。また&&、改行の代わりに行を連結する価値もあります。
シルコリント

2
残念ながら、回答のリンクは機能していないようです。
ThomasW 2012

リンクが停止しているだけでなく、WOTの評判が悪いという警告があります。したがって、私はそれを削除しました。
ジャン=フランソワ・コルベット

93

別の方法があります:

git checkout -p

それはとの混合でgit checkoutありgit add -p、あなたが探しているものとまったく同じかもしれません:

   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.

10
マージできる変更の数が管理可能な数だけある限り、これははるかに簡単で最も簡単な方法です。この回答にもっと多くの人が気づき、賛成してくれることを願っています。例:git checkout --patch exp1 file_to_merge
Tyler Rick

1
同様の回答がこの質問に投稿されました:stackoverflow.com/a/11593308/47185
タイラーリック、

ああ、チェックアウトにパッチがあることを知りませんでした!代わりに、チェックアウト/リセット/追加-pを行いました。
ダニエルC.ソブラル

2
本当に最も簡単な方法。git checkout -p featurebranchファイル名。そして、最良のことは、コマンドが実行されたときに、y / n / e /?/ ... etcを提供することです。ファイルのマージ方法を決定するオプション。eで試しましたが、適用する前にパッチを編集することもできました。他のブランチから選択したファイルをマージするための真のワンライナー。
infoclogged 2016年

55

これらの回答のいくつかはかなり良いですが、実際にはOPの元の制約である特定のブランチから特定のファイルを選択することには、誰も回答していないようです。このソリューションはそれを行いますが、多くのファイルがある場合は退屈な場合があります。

あなたが考えてみましょうmasterexp1exp2枝を。各実験ブランチから1つのファイルをマスターにマージしたいとします。私はこのようなことをします:

git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b

# save these files as a stash
git stash
# merge stash with master
git merge stash

これにより、必要な各ファイルのファイル内差分が得られます。これ以上何もない。何も少ない。バージョン間で根本的に異なるファイルの変更がある場合に便利です。私の場合、アプリをRails 2からRails 3に変更します。

編集:これはファイルをマージしますが、スマートマージを行います。私はこの方法を使用してファイル内の差分情報を取得する方法を理解できませんでした(多分それでも極端な違いはあります。空白などの迷惑な小さなものは、-s recursive -X ignore-all-spaceオプションます)


4
また、指定されたブランチから複数のファイルをすべてインラインで実行することもできます。例git checkout exp1 path/to/file_a path/to/file_x
EMiller

2
これは美しいです。私がやったgit checkout feature <path>/*ファイルのグループを取得します。
isherwood 2014年

これは問題なく動作しますが、2つの追加のコミットオブジェクトが追加されました。
大した

@MightyPorkあなたは正しい。残念ながら、これはずっと前に書いたので、なぜ「git stash」と「git merge stash」のステップが「git commit」の代わりにそこにあるのか、もはやわかりません。
Eric Hu

2
ああ、それは明らかだと思います。この方法では、1つのファイルをマージしますが、ターゲットブランチの以前の変更を必ずしも上書きするわけではありません。
MightyPork 2015

48

1800 INFORMATIONの答えは完全に正しいです。ただし、git noobとして、「use cherry-pickを使用する」だけでは、インターネットで少し掘り下げずにこれを理解するのに十分ではなかったので、他の誰かが同様のボート。

私のユースケースでは、他の誰かのgithubブランチから自分の変更を選択的にプルしたいと考えていました。すでに変更を加えたローカルブランチがある場合は、手順2と5〜7を実行するだけで済みます。

  1. 取り込みたい変更を含むローカルブランチを作成します(作成されていない場合)。

    $ git branch mybranch <base branch>

  2. それに切り替えます。

    $ git checkout mybranch

  3. 他の人のアカウントから必要な変更を引き出します。まだ追加していない場合は、リモートとして追加する必要があります。

    $ git remote add repos-w-changes <git url>

  4. 彼らの枝からすべてを引き出します。

    $ git pull repos-w-changes branch-i-want

  5. コミットログを表示して、必要な変更を確認します。

    $ git log

  6. 変更をプルするブランチに切り替えます。

    $ git checkout originalbranch

  7. チェリーはハッシュを使用してコミットを1つずつ選択します。

    $ git cherry-pick -x hash-of-commit

ハットチップ:http : //www.sourcemage.org/Git_Guide


3
ヒント:まずgit cherryコマンド(最初にマニュアルを参照)を使用して、まだマージしていないコミットを特定します。
akaihola

これは機能します.. 1.新しいブランチを作成しました2.いくつかのファイルを作成しました/いくつかの変更を加えました3.コミット4.マスターブランチをチェックアウトします5.gitチェリーピック-xハッシュのコミットを実行し、マージの競合を解決しますトーゴ。
RamPrasadBismil

リンクは機能していません。更新して頂けますか?
creep3007

42

ここでは、置き換えることができる方法であるMyclass.java内のファイルmasterとブランチをMyclass.javaしてfeature1ブランチ。にMyclass.java存在しなくても機能しmasterます。

git checkout master
git checkout feature1 Myclass.java

これはマージではなく上書きされ、マスターブランチのローカルの変更は無視されます。


6
これはマージされません。マスターの変更をfeature1ブランチからの変更で上書きするだけです。
Skunkwaffle 2013

3
完全に、私はこの種類のマージを探していました。theirs上書きours=> +1乾杯;)
olibre

1
場合によっては、ファイル全体を置き換えるだけでよい場合があります。これが私が望んでいたことですが、このファイルに加えたすべての変更を確実に失わせる必要があります。
MagicLAMP 2014

1
OPがファイル全体を別のブランチの同等のもので具体的に置き換えたいと考えた場合、最もクリーンなソリューション:2. Manual copying of common files into a temp directory followed by ...copying out of the temp directory into the working tree.
Brent Faust

29

特定のファイルを別のブランチのファイルで置き換えるだけでなく、2つのブランチの特定のファイルを実際にマージする簡単な方法。

ステップ1:ブランチを比較する

git diff branch_b > my_patch_file.patch

現在のブランチとbranch_bの違いのパッチファイルを作成します

ステップ2:パターンに一致するファイルにパッチを適用する

git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch

オプションに関する有用なメモ

*includeパターンでワイルドカードとして使用できます。

スラッシュはエスケープする必要はありません。

また、代わりに--excludeを使用して、パターンに一致するファイルを除くすべてに適用するか、-Rを使用してパッチを元に戻すことができます

-p1オプションは* unix patchコマンドからのホールドオーバーであり、パッチファイルの内容が各ファイル名の前にa/またはb/あなたはそれを把握することができますことをストリップする必要があります(パッチファイルが生成されたかに応じて、またはそれ以上)パッチが適用される必要があるファイルへのパスへの実際のファイル。

その他のオプションについては、git-applyのmanページを確認してください。

ステップ3:ステップ3はありません

変更をコミットしたいのは明らかですが、コミットする前に行う必要のある他の関連する微調整がないと言うのは誰でしょう。


1
これは、current_branchに保持する必要のある多くの「追加」変更がある場合に非常に役立ちました。git diff HEAD ... branch_b(はい、3つのピリオドで手品を行います)として、branch_bによってもたらされた変更のみの差分を得ました。
Saad Malik

@masukomi、ステップ2で、ステップ1で作成したパッチファイルを引数として追加しないでください。
Spiralis 2016年

私にとって、すべての変更は拒否されます。なぜか?
LinusGeffarth

@LinusGeffarthの最初の考えは、パッチを作成するときにブランチを逆方向に取得したことですか?SOの外でフォローアップして、理解できるかどうかを確認します。
ますこみ

24

より単純なマージで不要な変更がさらに多く発生したとしても、別のブランチからほんのわずかなファイルをたどって履歴を追跡する方法を以下に示します。

最初に、作業ディレクトリ内のファイルに対してgitが何もしないで、コミットしようとしているのがマージであることを事前に宣言するという異常な手順を実行します。

git merge --no-ff --no-commit -s ours branchname1

。。。ここで、「branchname」は、マージ元であると主張するものです。すぐにコミットすると、変更は行われませんが、他のブランチの祖先が表示されます。ブランチ/タグ/その他を追加できます。必要に応じて、コマンドラインにも同様に。ただし、この時点ではコミットする変更はないので、次に他のリビジョンからファイルを取得します。

git checkout branchname1 -- file1 file2 etc

他の複数のブランチからマージする場合は、必要に応じて繰り返します。

git checkout branchname2 -- file3 file4 etc

これで、他のブランチのファイルがインデックスに登録され、コミットできるようになり、履歴が追加されます。

git commit

そのコミットメッセージでやるべきことをたくさん説明するでしょう。

ただし、不明確な場合は、これを行うのはめちゃくちゃであることに注意してください。これは「ブランチ」の趣旨に沿ったものではありません。チェリーピックは、ここで行うことを行うためのより正直な方法です。前回持ってこなかった同じブランチ上の他のファイルに対して別の「マージ」を実行したい場合は、「すでに最新」のメッセージが表示されて停止します。これは、「from」ブランチで複数の異なるブランチを使用する必要があるときに、ブランチが作成されないという症状です。


3
最初のコマンド(git merge --no-ff --no-commit -s outs branchname1)はまさに私が探していたものです!ありがとう!
RobM

1
複数のブランチがあり、必要な履歴があり、単一のファイルをマージし、プッシュする前にファイルのコンテンツを変更する必要がある場合、これはまともな代替手段のようです。たとえば、dev => masterですが、masterにプッシュする前にホスト定義などを変更したいとします。
timss 2014年

15

私は少し遅れていることを知っていますが、これは選択したファイルをマージするための私のワークフローです。

#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes 
git merge --no-commit  featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit

私はこれに少し変化をつけました。マージする代わりに、私はチェリーピックしました。それは仕事をします。このアプローチの唯一の欠点は、元のコミットハッシュへの参照を失うことです。
Matt Florence、

15

最も簡単な方法は、マージするブランチにリポジトリを設定して実行することです。

git checkout [branch with file] [path to file you would like to merge]

走れば

git status

ステージング済みのファイルが表示されます...

次に実行します

git commit -m "Merge changes on '[branch]' to [file]"

シンプル。


3
これが私が見つけたほぼ最良の答えです。jasonrudolph.com/blog/2009/02/25/…を参照してください とても明確で簡潔であり、機能します!
superuseroi

1
マージするのではなく、ソースブランチのファイルコンテンツを完全に置き換える
Amare

こんなふうに答えようとしていたところ、まだ答えられていない新しいことを発明しようと思った!しかし、これが最も簡単な方法です。これは上にあるはずです!
Irfandy Jip

15

この投稿には最も単純な答えが含まれていることがわかりました。単に行います:

$ #git checkout <branch from which you want files> <file paths>

例:

$ #pulling .gitignore file from branchB into current branch
$ git checkout branchB .gitignore

詳細については、投稿を参照してください。


3
これは実際にはマージせず、現在のブランチ上のファイルを上書きします。
イゴールラリック14

1
@igraliこれは便利なコメントですが、これを行う「適切な」方法の難しさと比較すると、これは良い回避策です。非常に注意が必要です。
オーウェンスマーティン2014

12

gitに「すぐに使える」便利なツールがまだないのは奇妙です。現在のバージョンのブランチからのいくつかのバグ修正によって、古いバージョンのブランチ(まだ多くのソフトウェアユーザーがいる)を更新するときに、私はそれを頻繁に使用します。この場合、多くの場合、すぐに取得するために必要とされているだけでいくつかの(古いバージョンに行くことになっていない)他の多くの変更を無視して、トランク内のファイルからのコードの行を...そしてもちろん、インタラクティブな3ウェイマージこの場合は必要ですが、このgit checkout --patch <branch> <file path>選択的マージの目的には使用できません。

あなたはそれを簡単に行うことができます:

次の行を[alias]グローバルファイル.gitconfigまたはローカル.git/configファイルのセクションに追加するだけです。

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"

Beyond Compareを使用することを意味します。必要に応じて、選択したソフトウェアに変更してください。または、インタラクティブな選択的マージが必要ない場合は、3者間自動マージに変更できます。

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"

次に、このように使用します:

git mergetool-file <source branch> <file path>

これにより、他のブランチにある任意のファイルのみの真の選択的ツリー方式マージ機会が得られます。


10

それは正確にあなたが探していたものではありませんが、私にとっては役に立ちました:

git checkout -p <branch> -- <paths> ...

それはいくつかの答えの混合です。


2
これは本当に便利で、私にとって最良の答えである@alvinabadの答えに追加できます。実行時:git checkout HEAD file1現在のバージョンを維持してファイルをマージ解除するために、マージするファイルの一部を選択file1する-pオプションを使用できます。トリックをありがとう!
Simon C.

これは私のお気に入りの答えです。シンプルで要点があり、機能する
Jesse Reza Khorasanee

8

私はするだろう

git diff commit1..commit2 filepattern | git-apply --index && git commit

このようにして、ブランチからのファイルパターンのコミットの範囲を制限できます。

盗まれた場所:http : //www.gelato.unsw.edu.au/archives/git/0701/37964.html


状況によっては、これは非常に便利です。ただし、変更が別のブランチにある場合は、上記のBart Jの回答のように、そのブランチの先端からチェックアウトできます。
cdunn2001

バートJsは誰ですか?
ブラック

8

私は上記のあなたが述べたのとまったく同じ問題を抱えていました。しかし、私は答えを説明することで、このgitブログをより明確にしました。

上記のリンクからのコマンド:

#You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>

これをテストしましたか?私は確かにファイルは<branch_you_want_to_merge_from>から置換されるのではなくマージされています
アマーレ

7

上記の「git-interactive-merge」の回答が好きですが、もっと簡単な方法があります。gitにインタラクティブとオンのリベースの組み合わせを使用してこれを実行させます:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master

したがって、C1とC2を「機能」ブランチ(ブランチポイント「A」)から取得したいが、残りは現時点では必要ない場合です。

# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp

これにより、上記のように、C1とC2の「選択」行を選択するインタラクティブエディターが表示されます(上記のとおり)。保存して終了すると、リベースが続行され、ブランチ「temp」とマスター+ C1 + C2にHEADが表示されます。

      A---C1---o---C2---o---o feature
     /
----o---o---o---o-master--C1---C2 [HEAD, temp]

次に、masterをHEADに更新してtempブランチを削除すれば、準備は完了です。

# git branch -f master HEAD
# git branch -d temp

7

どうですか git reset --soft branchですか?まだ誰も言及していないことに驚いています。

私にとって、このコマンドは別のブランチから変更を選択的に選択する最も簡単な方法です。このコマンドは作業ツリーに入れられ、すべてのdiffの変更を反映し、必要なものを簡単に選択または元に戻すことができます。このようにして、コミットされたファイルを完全に制御できます。


6

この質問が古く、他にも多くの回答があることは知っていますが、ディレクトリを部分的にマージするために、「pmerge」という独自のスクリプトを書きました。それは進行中の作業であり、私はまだgitとbashスクリプトの両方を学習しています。

このコマンドは git merge --no-commit、指定されたパスと一致しない変更をして適用を解除します。

使用法:git pmerge branch path
例:git merge develop src/

私はそれを広範囲にテストしていません。作業ディレクトリには、コミットされていない変更や追跡されていないファイルがあってはなりません。

#!/bin/bash

E_BADARGS=65

if [ $# -ne 2 ]
then
    echo "Usage: `basename $0` branch path"
    exit $E_BADARGS
fi

git merge $1 --no-commit
IFS=$'\n'
# list of changes due to merge | replace nulls w newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
    [[ $f == $2* ]] && continue
    if git reset $f >/dev/null 2>&1; then
        # reset failed... file was previously unversioned
        echo Deleting $f
        rm $f
    else
        echo Reverting $f
        git checkout -- $f >/dev/null 2>&1
    fi
done
unset IFS


3

ファイルによる選択的なマージ/コミットのための簡単なアプローチ:

git checkout dstBranch git merge srcBranch // make changes, including resolving conflicts to single files git add singleFile1 singleFile2 git commit -m "message specific to a few files" git reset --hard # blow away uncommitted changes


3

変更されたファイルが多すぎない場合は、余分なコミットは行われません。

1.ブランチを一時的に複製する
$ git checkout -b temp_branch

2.最後に必要なコミットにリセットします。
$ git reset --hard HEAD~nここnで、戻る必要があるコミットの数です

3.元のブランチから各ファイルをチェックアウトします
$ git checkout origin/original_branch filename.ext

これで、必要に応じて、(リモートを上書きするために)コミットしてプッシュを強制できます。


3

あなただけそのまま他の特定のディレクトリや休暇のすべてをマージし、まだ歴史を維持する必要がある場合は、おそらくこれを試みることができる...新しい作成target-branchのオフをmasterあなたが実験前。

以下の手順では、2つのブランチtarget-branchsource-branchがあり、dir-to-mergeマージするディレクトリがにあると想定していますsource-branch。またdir-to-retain、ターゲットのように、変更して履歴を保持したくない他のディレクトリがあるとします。また、にマージの競合があることを前提としていdir-to-mergeます。

git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict. 
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.

# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.

2

2つのブランチの現在のコミットの間に変更されたファイルが数個しかない場合は、別のファイルを介して手動で変更をマージします。

git difftoll <branch-1>..<branch-2>

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