wake-up-neo.com

Git Cherry-Pick vs Merge Workflow

Angenommen, ich bin der Verwalter eines Repos und möchte Änderungen von einem Mitwirkenden übernehmen, dann gibt es ein paar mögliche Workflows:

  1. ICH cherry-pick jedes Commit von der Fernbedienung (in Reihenfolge). In diesem Fall zeichnet git das Commit als nicht mit dem entfernten Zweig verbunden auf.
  2. Ich merge den Zweig, ziehe alle Änderungen ein und füge einen neuen "Konflikt" -Commit hinzu (falls erforderlich).
  3. I merge jedes Commit von der Remote-Verzweigung einzeln (wieder in der richtigen Reihenfolge), sodass Konflikte für jedes Commit aufgezeichnet werden können, anstatt alle als ein Commit zu gruppieren.
  4. Der Vollständigkeit halber könnten Sie ein rebase (dasselbe wie cherry-pick Option?), jedoch kann dies nach meinem Verständnis Verwirrung stiften. Möglicherweise entfällt dadurch Option 1.

In beiden Fällen 2 und 3 zeichnet git im Gegensatz zu 1 die Verzweigungshistorie der Commits auf.

Was sind die Vor- und Nachteile zwischen der Verwendung von entweder cherry-pick oder merge beschriebene Methoden? Nach meinem Verständnis ist Methode 2 die Norm, aber ich bin der Meinung, dass die Lösung eines großen Commits mit einer einzigen "Konflikt" -Mischung nicht die sauberste Lösung ist.

289
cmcginty

Sowohl rebase (und cherry-pick) Als auch merge haben ihre Vor- und Nachteile. Ich argumentiere hier für merge, aber es lohnt sich, beide zu verstehen. (Suchen Sie hier nach einer alternativen, gut argumentierten Antwort Aufzählung von Fällen, in denen rebase bevorzugt wird.)

merge wird aus mehreren Gründen gegenüber cherry-pick Und rebase bevorzugt.

  1. Robustheit . Die SHA1-Kennung eines Commits identifiziert es nicht nur an sich, sondern auch in Bezug auf alle anderen Commits, die ihm vorausgehen. Dies bietet Ihnen die Garantie, dass der Status des Repositorys bei einem bestimmten SHA1 über alle Klone hinweg identisch ist. Es gibt (theoretisch) keine Chance, dass jemand die gleiche Änderung vorgenommen hat, aber tatsächlich Ihr Repository beschädigt oder entführt. Sie können einzelne Änderungen auswählen und sie sind wahrscheinlich gleich, aber Sie haben keine Garantie. (Als geringfügiges sekundäres Problem belegen die neu ausgewählten Commits zusätzlichen Speicherplatz, wenn jemand anderes erneut die gleichen Commits auswählt, da beide in der Historie vorhanden sind, auch wenn Ihre Arbeitskopien letztendlich identisch sind.)
  2. Benutzerfreundlichkeit . Die Leute verstehen den merge Workflow ziemlich leicht. rebase wird tendenziell als weiter fortgeschritten angesehen. Es ist am besten, beides zu verstehen, aber Leute, die keine Experten in der Versionskontrolle sein wollen (zu denen meiner Erfahrung nach viele Kollegen gehören, die verdammt gut darin sind, was sie tun, aber die zusätzliche Zeit nicht verbringen wollen), haben es leichter Zeit verschmilzt gerade.

Selbst bei einem zusammenführungsintensiven Workflow sind rebase und cherry-pick In bestimmten Fällen immer noch nützlich:

  1. Ein Nachteil von merge ist die überfüllte Historie. rebase verhindert, dass eine lange Reihe von Festschreibungen in Ihrem Verlauf verstreut ist, wie dies der Fall wäre, wenn Sie regelmäßig Änderungen anderer vornehmen. Das ist in der Tat sein Hauptzweck, wie ich es benutze. Was Sie sehr vorsichtig sein möchten, ist, niemals Code zu rebase, den Sie mit anderen Repositorys geteilt haben. Sobald ein Commit Push ausgeführt wurde, hat möglicherweise eine andere Person das Commit ausgeführt, und ein erneutes Basieren führt bestenfalls zu der oben beschriebenen Art von Duplikation. Im schlimmsten Fall kann es zu einem sehr verwirrten Repository und subtilen Fehlern kommen. Das Aufspüren dauert lange.
  2. cherry-pick Ist nützlich, um eine kleine Teilmenge von Änderungen aus einem Zweig herauszusuchen, für den Sie sich grundsätzlich entschieden haben, ihn aber zu verwerfen.

Wenn Sie es vorziehen, viele Änderungen über eine zu verschmelzen, ist dies viel einfacher. Es kann sehr mühsam werden, einzelne Änderungssätze zusammenzuführen, sobald Sie anfangen, viele davon zu haben. Die Zusammenführungsauflösung in Git (und in Mercurial und in Bazaar) ist sehr, sehr gut. Sie werden die meiste Zeit nicht auf große Probleme stoßen, selbst lange Zweige zusammenzuführen. Im Allgemeinen füge ich alles auf einmal und nur dann zusammen , wenn ich eine große Anzahl von Konflikten bekomme, mache ich ein Backup und führe die Zusammenführung stückweise erneut aus. Selbst dann mache ich es in großen Stücken. Als ein sehr reales Beispiel hatte ich einen Kollegen, der 3 Monate lang Änderungen zum Zusammenführen hatte und ungefähr 9000 Konflikte in 250000 Zeilen Code-Basis hatte. Was wir getan haben, um das Problem zu beheben, ist, die Zusammenführung um jeweils einen Monat zu lösen: Konflikte häufen sich nicht linear an, und wenn wir sie in Teilen lösen, werden weitaus weniger als 9000 Konflikte. Es war immer noch eine Menge Arbeit, aber nicht so viel wie der Versuch, es ein Commit nach dem anderen zu tun.

280
quark

Meiner Meinung nach sollte Kirschernte für seltene Situationen reserviert werden, in denen dies erforderlich ist, zum Beispiel wenn Sie einige Änderungen direkt am Hauptzweig (Stamm, Hauptentwicklungszweig) vorgenommen und dann festgestellt haben, dass es auch für die Wartung angewendet werden sollte '. Sie sollten den Workflow entweder auf Merge oder Rebase (oder "git pull --rebase") basieren.

Bitte denken Sie daran, dass das von Cherry gepflückte oder neu basierende Commit aus Sicht von Git anders ist (hat eine andere SHA-1-ID) als das Original, es unterscheidet sich also vom Commit im Remote-Repository. (Rebase kann normalerweise damit umgehen, da es die Patch-ID prüft, d. H. Die Änderungen, keine Festschreibungs-ID).

Auch in Git können Sie mehrere Zweige gleichzeitig zusammenführen: sog. Octopus Merge . Beachten Sie, dass die Octopus-Zusammenführung ohne Konflikte erfolgreich sein muss. Trotzdem könnte es nützlich sein.

HTH.

93
Jakub Narębski