325

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

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

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

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

4

3 に答える 3

320

rebase(およびcherry-pick) との両方mergeに長所と短所があります。私はここで議論しmergeますが、両方を理解する価値があります。(ここを見てくださいrebase

mergecherry-pickおよびrebaseいくつかの理由で優先されます。

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

マージが多いワークフローrebaseであっcherry-pickても、特定のケースでは依然として有用です。

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

1つよりも多くの変更をマージすることを好むことに関しては、それははるかに簡単です。チェンジセットがたくさんあると、個々のチェンジセットをマージするのは非常に面倒です。git (および Mercurial、Bazaar) でのマージの解決は非常に優れています。ほとんどの場合、長いブランチをマージしても大きな問題に遭遇することはありません。私は通常、すべてを一度にマージし、多数の競合が発生した場合にのみ、マージを少しずつバックアップして再実行します。それでも私は大きな塊でそれをします。非常に現実的な例として、3 か月分の変更をマージする必要があり、250000 行のコードベースで約 9000 の競合が発生した同僚がいます。修正するために行ったのは、一度に 1 か月分のマージを行うことです。競合は直線的に蓄積されず、バラバラに行うと結果が大きく変わります。9000 未満の競合。それでも大変な作業でしたが、一度に 1 つのコミットを実行しようとするほどではありませんでした。

于 2009-08-06T22:14:19.000 に答える
102

私の意見では、チェリーピッキングは、必要なまれな状況のために予約する必要があります。たとえば、「マスター」ブランチ(トランク、メイン開発ブランチ)で直接修正を行った後、「メイン」ブランチにも適用する必要があることに気付いた場合などです。 '。ワークフローは、マージまたはリベース(または「gitpull--rebase」)に基づいて作成する必要があります。

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

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

HTH。

于 2009-08-08T12:22:19.410 に答える