git:あるリポジトリのコミットで導入された変更を別のリポジトリに適用する


115

私が持っているrepo1repo2、ローカルマシン上で。それらは非常に似ていますが、後者はある種の他のブランチです(repo1もう保守されていません)。

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

コミットによる変更の適用方法<some_sha>repo1するのrepo2

パッチを準備する必要がありますか、それともcherry-pickリポジトリの間にパッチを作成することは可能ですか?

同じことをしますが、コミットの範囲についてはどうですか?


2
repo1からrepo2にプルすることはできませんか?
zwol 2010

あなたがリポジトリの1つに移動されたファイルまたはファイルに変更を適用するために探している、もう少し具体的な場合のために、ここを見て:stackoverflow.com/questions/3491270/...
Brahamスナイダー

回答:


31

ハックとして、GitTipsページの2つの異なるリポジトリでコミットを比較するためのレシピを変更してみてください

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

ここで、../repo他のリポジトリへのパスです。

最新のGitでは、cherry-pickで複数のリビジョンとリビジョン範囲を使用できます。

$(git --git-dir=../repo/.git rev-parse --verify <commit>) 翻訳するためにここにある<commit>(例えばHEAD、またはv0.2、またはmaster~2コミットのSHA-1の識別子にコピー元二リポジトリ内の値です)。選択する変更のSHA-1がわかっている場合は、必要ありません。

ただし、Gitはソースリポジトリからのオブジェクトのコピーをスキップできることに注意してください。これは、代替オブジェクトリポジトリが一時的なものであることが1つの操作で認識されないためです。次のようにして、2番目のリポジトリからオブジェクトをコピーする必要がある場合があります。

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

これにより、2番目のリポジトリから借用したオブジェクトが元のリポジトリストレージに配置されます

未検証。


それほどハッキーではない解決策は、ニットの答えに従うことです

  • コミットをコピーする2番目のリポジトリに移動し、必要なコミットからパッチを生成します git format-patch
  • 必要に応じて、パッチ(0001- *など)をリポジトリにコピーします
  • git am --3wayパッチの適用に使用します

1
うまくいきます。コミットに問題がある場合は、 'git reset HEAD; git add。 '。
gumik 2012年

5
これは素晴らしいです-一連のコミットをどのように行いますか?sha1 ... sha2?
hvgotcodes 2013年

私も取得しますfatal: unable to read tree ...が、git reset HEAD^すべてが
正常に

@hvgotcodesは範囲を渡すだけで機能しました<commit>が、rev-parse --verifyコマンドは単一のコミット値しか受け入れないため、コマンドはそれを好みません。しかしcherry-pick、単一と範囲の両方のコミット値を受け入れるので、私は尋ねます:なぜrev-parse必要なのですか?
2015年

1
@Chuim:git rev-parseコミットを他のリポジトリの参照ベースの名前で参照する場合に必要です(例:masterなどHEAD^^)。rev-parseはそれをユニバーサルSHA-1識別子に変換します。
JakubNarębski、2015年

207

おそらく使いたい git format-patchと、その後git am、あなたのリポジトリにそのパッチを適用します。

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

または、1行で:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
このソリューションは、ダイレクトチェリーピッキングを使用するという一般に認められている回答よりも単純で安全であることが証明されましたGIT_ALTERNATE_OBJECT_DIRECTORIES(リポジトリが破損する可能性があります)。
2015年

2
競合がある場合、他のブランチでコミットを見つけることができないため、機能しません。
ロジャーファー

2
コマンドに追加する--ignore-whitespaceと、git amすべての競合が解決され、3者間マージを実行する必要が
なくなる

97

cherry-pick2番目のリポジトリを最初のリポジトリとしてリモートとして追加すると(そして次にfetch)、それを行うことができます。


11
それは実際にそれを行う適切な方法です。
Wilbert

5
これは私にとっても正しい方法のように感じます。そして私はそれを使用しただけで、それは私にとってはうまくいきました。
リッキーネルソン

10
私はむしろ言いたい:git fetch [remote-name]2番目のリポジトリで実行し、次にgit cherry-pick [sha1]

5
おかげで、このアプローチは私にとってはうまくいきました。2番目のリポジトリもローカルであるため、リモートとして追加するときにファイルURIを使用する必要がありました。
palimpsestor 2015

2
私の場合、巨大なリモートgitリポジトリの2つのクローンがあり(並列作業を可能にするため)、その履歴はすべてダウンロードされ、HDに2回保存されています。それぞれをもう一方のリモートとしても追加する必要がある場合、同じ履歴の2つの追加コピーが作成され、可能になる前にそれらの間の同期が必要になる可能性がありますcherry-pick。したがって、「正しい」方法のように感じるかもしれませんが、それが常に最も実用的であるとは限りません。
Chuim、2015年

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