master
ブランチがあると想像してください。
次に、newbranch
を作成します
git checkout -b newbranch
newbranch
に2つの新しいコミットを作成します。commit1およびcommit2
次に、マスターに切り替えてcherry-pick
を作成します
git checkout master
git cherry-pick hash_of_commit1
gitk
を調べると、commit1とチェリーピッキングバージョンのハッシュが異なるため、技術的には2つの異なるコミットです。
最後に、newbranch
をmaster
にマージします。
git merge newbranch
異なるハッシュを持つこれらの2つのコミットは問題なくマージされましたが、同じ変更を2回適用する必要があるため、そのうちの1つが失敗することがわかります。
Gitはマージの内容を本当にスマートに分析し、変更を2回適用しないか、これらのコミットが内部でリンクされているとマークされているかを決定しますか?
心配しないでください。Gitが処理します。
例とは異なりSVN1、Gitはコミットをデルタ形式で保存しませんが、snapshot-basedです2,3。 SVNはマージされた各コミットをパッチとして単純に適用しようとします(そして、説明したとおりの理由で失敗します)が、Gitは通常このシナリオを処理できます。
マージするとき、Gitは両方のHEADコミットのスナップショットを新しいスナップショットに結合しようとします。コードまたはファイルの一部が両方のスナップショットで同一である場合(つまり、コミットが既にチェリーピッキングされているため)、Gitはそれに触れません。
ソース
このようなマージの後、履歴でチェリーピックされたコミットが2回発生する場合があります。
これを防ぐための解決策は、 article から引用します。これは、重複する(チェリーピックの)コミットを持つブランチに対して、マージ前にリベースを使用することを推奨します。
git cherry-pick後のgit merge:重複したコミットの回避
マスターブランチとブランチbがあるとします:
o---X <-- master \ b1---b2---b3---b4 <-- b
今、masterにコミットb1とb3が緊急に必要ですが、bに残っているコミットは必要ありません。したがって、マスターブランチをチェックアウトし、チェリーピックコミットb1およびb3を実行します。
$ git checkout master $ git cherry-pick "b1's SHA" $ git cherry-pick "b3's SHA"
結果は次のようになります。
o---X---b1'---b3' <-- master \ b1---b2---b3---b4 <-- b
マスターで別のコミットをすると、次のようになります:
o---X---b1'---b3'---Y <-- master \ b1---b2---b3---b4 <-- b
ブランチbをマスターにマージする場合:
$ git merge b
次のものが得られます。
o---X---b1'---b3'---Y--- M <-- master \ / b1----b2----b3----b4 <-- b
これは、b1とb3によって導入された変更が履歴に2回現れることを意味します。それを避けるために、マージの代わりにリベースできます:
$ git rebase master b
どちらが得られますか:
o---X---b1'---b3'---Y <-- master \ b2'---b4' <-- b
最後に:
$ git checkout master $ git merge b
私たちに与えます:
o---X---b1'---b3'---Y---b2'---b4' <-- master, b
編集デビッドレモンのコメントが想定している修正