web-dev-qa-db-ja.com

Git Cherry-pickとマージワークフロー

私がレポジトリのメンテナーであり、寄稿者から変更を取得したいと仮定すると、いくつかの可能なワークフローがあります:

  1. リモートからのコミットごとにcherry-pick(順番に)。この場合、gitはコミットをリモートブランチとは無関係として記録します。
  2. 私はブランチをmerge、すべての変更を取り込み、新しい「競合」コミットを追加します(必要な場合)。
  3. I mergeリモートブランチからの各コミットを個別に(順番に)個別にグループ化するのではなく、コミットごとに競合を記録できるようにします。
  4. 完全を期すために、rebasecherry-pickオプションと同じ?)を行うこともできますが、私の理解では、これにより投稿者に混乱が生じる可能性があります。多分それはオプション1を排除します。

ケース2と3の両方で、gitは1とは異なり、コミットのブランチ履歴を記録します。

説明されているcherry-pickまたはmergeメソッドを使用することの長所と短所は何ですか?私の理解では、方法2が標準であるが、単一の「競合」マージで大きなコミットを解決することはそうではないと感じています最もクリーンなソリューション。

288
cmcginty

rebase(およびcherry-pick)とmergeには両方とも長所と短所があります。ここではmergeについて議論していますが、両方を理解する価値があります。 (別の、よく議論された answerrebaseが望ましいケースを列挙するためにここを見てください。)

mergeは、いくつかの理由により、cherry-pickおよびrebaseよりも優先されます。

  1. 堅牢性。コミットのSHA1識別子は、それ自体だけでなく、その前にある他のすべてのコミットもに関連して識別します。これにより、特定のSHA1でのリポジトリの状態がすべてのクローンで同一であることが保証されます。 (理論上)誰かが同じ変更のように見えることを行ったが、実際にはリポジトリを破壊またはハイジャックしている可能性はありません。個々の変更をチェリーピックすることができ、それらはおそらく同じですが、保証はありません。 (マイナーな二次問題として、同じチェリーピックされた新しいチェリーピックコミットは、同じコピーでチェリーピックされた場合、余分なスペースを占有します。作業コピーが最終的に同一であっても、両方とも履歴に存在します。)
  2. 使いやすさ。人々はmergeワークフローをかなり簡単に理解する傾向があります。 rebaseは、より高度であると考えられる傾向があります。両方を理解することをお勧めしますが、バージョン管理の専門家になりたくない人(私の経験では、自分の仕事に長けているが、余分な時間を使いたくない多くの同僚が含まれています)マージするだけの時間です。

マージが多いワークフローでも、rebasecherry-pickは特定の場合に役立ちます:

  1. mergeのマイナス面の1つは、雑然とした履歴です。 rebaseは、他の変更に定期的にマージする場合のように、長い一連のコミットが履歴に散らばることを防ぎます。それは実際、私が使用するときの主な目的です。 veryになりたいのは、他のリポジトリと共有しているrebaseコードを使用しないことです。コミットがPushedになると、他の誰かがその上でコミットした可能性があり、リベースはせいぜい上記で説明した種類の重複を引き起こします。最悪の場合、非常に混乱したリポジトリと微妙なエラーが発生する可能性があり、フェレットを見つけるのに時間がかかります。
  2. cherry-pickは、基本的に破棄することを決定したトピックブランチから変更の小さなサブセットをサンプリングするのに役立ちますが、いくつかの有用な部分があることに気付きました。

1つよりも多くの変更をマージすることを好むということに関しては、それははるかに単純です。多くの変更セットを取得し始めると、個々の変更セットをマージするのは非常に退屈になります。 git(およびMercurial、およびBazaar)のマージ解像度は非常に優れています。ほとんどの場合、長いブランチをマージしても大きな問題は発生しません。私は通常、すべてを一度にすべてマージしますifマージの断片をバックアップして再実行すると、多数の競合が発生します。それでも、私は大きな塊でそれを行います。非常に現実的な例として、3か月分の変更をマージする同僚がいて、250000行のコードベースで9000件の競合が発生しました。修正するために行ったのは、マージを一度に1か月分実行することです。競合は直線的に蓄積せず、分割して行うとfar 9000未満の競合になります。まだ多くの作業がありましたが、一度に1つのコミットをしようとするほどではありませんでした。

278
quark

私の意見では、チェリーピッキングは必要なまれな状況、たとえば「マスター」ブランチ(トランク、メイン開発ブランチ)で直接修正を行い、それが「メイント」 '。マージまたはリベース(または「git pull --rebase」)のいずれかに基づいてワークフローを作成する必要があります。

チェリーピックまたはリベースされたコミットは、Gitの観点から異なるものであり(元のSHA-1識別子とは異なる)、元のコミットとは異なるため、リモートリポジトリ。 (Rebaseは通常、パッチID、つまりコミットIDではなく変更をチェックするため、これに対処できます)。

また、gitでは、多数のブランチを一度にマージできます。いわゆるoctopus merge。タコのマージは競合なしで成功する必要があることに注意してください。それにもかかわらず、それは役に立つかもしれません。

HTH。

92
Jakub Narębski