GITを使用して、あるコミットからの変更を別の「フォーク」に選択的にマージするにはどうすればよいですか?


81

このシナリオを考えてみましょう。

  1. github.comでコードベースを「フォーク」することにし、ルーチンを開始します。編集-コミット-プッシュ; 別名ハックハックハック。
  2. いくつか変更を加えた後、同じプロジェクトで他の人が行った変更をいくつか見て、気に入っています。
  3. 私はそれらを私のものにマージしたいと思います。問題は、彼が行ったいくつかのコミットのうち、1つの特定のコミットの「部分」だけが必要なことです。

これらの選択された量の変更を取得して、私の「フォーク」にマージする最も効率的な方法は何でしょうか?



回答:


119

IRCの世界の波をトローリングした後、誰かが素晴らしい解決策を提供しました。

git cherry-pick SHA1 --no-commit
git add --patch

うまくいけば、それは同じ質問を持つ他の人を助けるでしょう!

編集:わかりました、多分それはそれほど単純ではありません。完全な手順は次のとおりです。

  1. まず、リポジトリにいる必要cdがあります。必要な-ingを実行して、作業ディレクトリにアクセスします。

  2. 次に、リモートブランチを追加して、それをフェッチする必要があります。これを行うには:

    git remote add someUser git://github.com/someUser/someRepo.git

    git fetch someUser

  3. これでgit log someUser/master、マージするコミットSHA1を「部分的に」見つけるなどのコマンドを実行できます。

  4. SHAを取得したら、次を実行できます。

    git cherry-pick -n SHA1

    SHA1コミットSHAはどこにありますか?

  5. コミットの古さや、プロジェクトの特定の領域が変更される頻度によっては、競合が発生する可能性があります。申し訳ありませんが、信頼できるエディターを使用してこれらを手動で解決する必要があります。したがって、VIMやその他の使用するものをすべて引き出し、変更が気に入った段階に到達するまで競合をハックします。

  6. ここで、インデックスをHEADリビジョンにリセットする必要があります。次に、trusty GITadd --patchコマンドを使用して、必要な変更を選択できます。

    git reset HEAD

    git add --patch または git add -p

  7. わーい!コミット時間:

    git commit -m "I merged a select amount of changes"

  8. 混乱(あなたがノーと言ったもの)をクリーンアップしgit add --patch、選択した変更のみを作業リポジトリに保持するには、次のコマンドを実行します。

    git reset --hard HEAD

    どうやらgit checkout -f別のオプションもあります。


あなたが見つけてくれてうれしいですgit add -p; それは非常に強力です。問題のコミットがすでにある場合(たとえば--no-commit、チェリーピックで使用しなかった場合、またはコミットの1つである場合)、git reset HEAD^インデックスを巻き戻してコミットを巻き戻し、変更を追加しgit add -pて、段階的にコミットすることができます。 。コミットがブランチのヒントにない場合はgit rebase -i、問題のコミットを使用して編集することを選択できます。
Cascabel

3
素敵なウォークスルー。あなただけしたい場合は覚えて全体がコミットあなただけ発し、-nこのように手順4で:git cherry-pick SHA1
Hulvej

ここで重要なのgit remote add <user> <fork-url>git cherry-pick、通常どおりにできることです。
トム

2

私はあなたが何を望んでいるのかはっきりしていません。他のフォークから特定のコミットのみを取り込みたい場合は、を使用できますgit cherry-pick SHAgitreadyの完全な説明。


私は、ある特定のコミットの「部分」/「セクション」/「数行」がリポジトリにマージされた後でのみです。特にファイル固有ではありません。
ティム

その場合、git format-patch SHA、git apply <patch>はオプションです
hgmnz 2009

2

私はTimのソリューションが本当に好きですが、vimdiffをいじくり回すのが好きなこともあります。この問題に対する私の解決策は大雑把ですが、vimが好きなのでうまくいきます。

私はvimdiffをdifftoolとして設定し、選択的にマージするためにブランチをdiffします。

git difftool <branch> <file>

次に、現在のブランチのバージョンが表示されているペインに移動し、vimでオリジナルを編集し(これが必要ない場合もありますが、vimdiffが/ tmpでバージョンを開く場合もあります)、読み取り専用モードを無効にします。

:e <file>
:set readonly!

これで、doやなどのvimのパッチツールを使用して、dp必要なものを適用したり、その他の小さな編集を行ったりすることができます。完了したら、ファイルを保存し、vimを終了してから、通常の編集のようにgitでファイルをステージングしてコミットします。

私が言ったように、これは特に洗練されていませんが、それは非常に強力であり、それでも純粋にコマンドラインにあります。gitにはマージメッセージが自動的に含まれないため、必ず明確なコミットメッセージを追加してください。

vimdiffの例http://j.mp/1dZVllt


この回答は、独立した本格的な回答としてふさわしいとは言えません。有用な情報ですが、特に関連性はありません。(なぜこれが答えの一番上にあるのですか?)
Mike Kormendy 2015

1

コミットのポートのみが必要な場合は、必要なコミットを選択し、触れたくないファイルをリセットすることをお勧めします。

git cherry-pick SHA1
git checkout HEAD file1 file2 ... fileN

もちろん、ファイルにいくつかの変更された部分があり、それらのいくつかだけを保持したい場合は、ファイルを手動で編集して、それらの変更を切り取るしかありません。


2
ここでチェックアウトは必要ですか?チェリーピックコマンドは、変更を作業ディレクトリに配置しませんか?
ケイシーワトソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.