Git Cherry-Pick gegen Merge Workflow

302

Angenommen, ich bin der Betreuer eines Repos und möchte Änderungen von einem Mitwirkenden übernehmen. Es gibt einige mögliche Workflows:

  1. Ich cherry-pickverpflichte mich jeweils von der Fernbedienung (in der Reihenfolge). In diesem Fall zeichnet git das Commit als nicht mit dem Remote-Zweig verbunden auf.
  2. Ich bin mergeder Zweig, ziehe alle Änderungen ein und füge ein neues "Konflikt" -Commit hinzu (falls erforderlich).
  3. Ich habe mergejedes Commit von der Remote-Verzweigung einzeln (wieder in der richtigen Reihenfolge) ausgeführt, sodass Konflikte für jedes Commit aufgezeichnet werden können, anstatt alle zu einem zusammenzufassen.
  4. Der Vollständigkeit halber könnten Sie eine rebase(wie cherry-pickOption?) Tun , aber ich verstehe, dass dies für den Mitwirkenden Verwirrung stiften kann. Vielleicht entfällt dadurch Option 1.

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

Was sind die Vor- und Nachteile zwischen der Verwendung von entweder cherry-pickoder den mergebeschriebenen Methoden? Mein Verständnis ist, dass Methode 2 die Norm ist, aber ich bin der Meinung, dass die Lösung eines großen Commits mit einer einzigen "Konflikt" -Zusammenführung nicht die sauberste Lösung ist.

cmcginty
quelle

Antworten:

297

Beide rebase(und cherry-pick) und mergehaben ihre Vor- und Nachteile. Ich argumentiere mergehier, aber es lohnt sich, beide zu verstehen. (Suchen Sie hier nach einer alternativen, gut argumentierten Antwort, in der Fälle aufgelistet werden, in denen dies rebasebevorzugt wird.)

mergeüber bevorzugt cherry-pickund rebasefür ein paar Gründe.

  1. Robustheit . Die SHA1-Kennung eines Commits identifiziert es nicht nur an und für sich, sondern auch in Bezug auf alle anderen Commits, die ihm vorausgehen. Dies bietet Ihnen eine Garantie dafür, dass der Status des Repositorys bei einem bestimmten SHA1 für alle Klone identisch ist. Es besteht (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 kleines sekundäres Problem nehmen die neuen Commits, die von Kirschen gepflückt wurden, zusätzlichen Platz ein, wenn jemand anderes erneut Kirschen auswählt, da beide in der Historie vorhanden sind, selbst wenn Ihre Arbeitskopien identisch sind.)
  2. Benutzerfreundlichkeit . Die Leute neigen dazu, den mergeWorkflow ziemlich leicht zu verstehen . rebaseneigt dazu, als fortgeschrittener angesehen zu werden. Es ist am besten, beides zu verstehen, aber Leute, die keine Experten für Versionskontrolle sein wollen (zu denen meiner Erfahrung nach viele Kollegen gehören, die verdammt gut in dem sind, was sie tun, aber keine zusätzliche Zeit verbringen wollen), haben es leichter Zeit nur verschmelzen.

Auch bei einem zusammenführungsintensiven Workflow rebaseund cherry-pickfür bestimmte Fälle immer noch nützlich:

  1. Ein Nachteil mergeist die überfüllte Geschichte. rebaseverhindert, dass eine lange Reihe von Commits in Ihrem Verlauf verstreut wird, wie dies der Fall wäre, wenn Sie die Änderungen anderer regelmäßig zusammenführen würden. Das ist in der Tat sein Hauptzweck, wie ich es benutze. Was Sie sehr vorsichtig sein möchten , ist niemals rebaseCode, den Sie mit anderen Repositorys geteilt haben. Sobald ein Commit pushbearbeitet wurde, hat möglicherweise jemand anderes darüber geschrieben, und ein erneutes Basieren führt bestenfalls zu der oben beschriebenen Art der Duplizierung. 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 Themenzweig herauszufiltern, den Sie grundsätzlich verworfen haben, aber festgestellt haben, dass es einige nützliche Teile gibt.

Wenn Sie es vorziehen, viele Änderungen einer vorzuziehen, ist dies viel einfacher. Es kann sehr mühsam werden, einzelne Änderungssätze zusammenzuführen, sobald Sie viele davon 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 zusammen und nur wenn ich eine große Anzahl von Konflikten bekomme, mache ich eine Sicherungskopie und führe die Zusammenführung stückweise erneut aus. Selbst dann mache ich es in großen Stücken. Als sehr reales Beispiel hatte ich einen Kollegen, der Änderungen im Wert von 3 Monaten zum Zusammenführen hatte und 9000 Konflikte in der 250000-Zeilencodebasis hatte. Was wir getan haben, um das Problem zu beheben, ist die Zusammenführung im Wert von jeweils einem Monat: Konflikte bauen sich nicht linear auf, und wenn Sie dies in Teilen tun, führt dies zu einer weitreichenden Auswirkungweniger als 9000 Konflikte. Es war immer noch viel Arbeit, aber nicht so viel wie der Versuch, es einzeln zu tun.

Quark
quelle
1
Theoretisch besteht die Möglichkeit, dass Mallory Ihr Repository beschädigen kann, indem Commits mit demselben SHA1, aber unterschiedlichem Inhalt erstellt werden. In der Praxis wird dies jedoch wahrscheinlich nie passieren. :)
Bombe
1
Ha :) Ich meinte "theoretisch sind die Chancen so gering, dass man sich darauf verlassen kann, dass es nicht passiert", aber Sie haben Recht, dass es auf den Kopf gestellt ist.
Quark
Was denkst du über "merge --squash"?
cmcginty
@Bombe Wenn Mallory erfolgreich sein will, müsste sie das ursprüngliche Commit und das zweite Commit mit demselben SHA1 erstellen. Eine andere Frage könnte also sein: Wie hoch ist die Wahrscheinlichkeit, dass zwei (etwas) falsche Commits auftreten und Sie es nicht bemerken? ;)
João Portela
64
9000 Konflikte? Ich würde meinen Job kündigen und Imker werden.
Sebastian Patten
95

Meiner Meinung nach sollte das Kirschpflücken für seltene Situationen reserviert werden, in denen es erforderlich ist, z. B. wenn Sie einige Korrekturen direkt am Hauptzweig (Stamm, Hauptentwicklungszweig) vorgenommen haben und dann erkannt haben, dass es auch auf die Wartung angewendet werden sollte '. Sie sollten den Workflow entweder auf Merge oder auf Rebase (oder "git pull --rebase") basieren.

Bitte denken Sie daran , dass Kirschverlesen oder umbasiert Commit verschieden vom Standpunkt der Git (hat verschiedenen SHA-1 identifier) als das Original, so dass er anders als die in entfernten Repository begehen. (Rebase kann normalerweise damit umgehen, da es die Patch-ID überprüft, dh die Änderungen, keine Commit-ID.)

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

HTH.

Jakub Narębski
quelle
19
+1 für den Punkt, an dem Rebase / Cherry-Picking die Commits tatsächlich "kopiert" und daher die Verknüpfung zum ursprünglichen Commit verliert.
Studgeek
1
Wir verwenden Cherry-Pick auf diese Weise ausschließlich, um Commits für Fehlerkorrekturen (möglicherweise SEHR KLEINE Funktionen) in einen vorhandenen Release-Zweig zu verschieben, um einen Patch vorzubereiten. Funktionen, die mehrere Commits umfassen, erfordern im Allgemeinen den Zugriff auf einen Release-Zweig, der nicht auf dem Master basiert.
Foxxtrot
3
@foxxtrot: Eine andere Lösung besteht darin, einen separaten Zweig für einen Bugfix zu erstellen, der auf dem ältesten Commit basiert, der diesen Fehler aufweist, und ihn in 'Main' und in 'Master' zusammenzuführen. In diesem Fall müssen Sie diesen Bugfix kennen gilt für beide Branchen.
Jakub Narębski
4
@Jakub Zwei Befehle, die für das Erstellen und Zusammenführen eines Bugfix-Zweigs unverzichtbar sind: git blameFinden des Commits, das den Fehler verursacht hat, und git branch --containsBestimmen, wo der Zweig zusammengeführt werden soll. Ausführlicher beschrieben in diesem Beitrag
gcbenison
-10

Rebase und Cherry-Pick sind die einzige Möglichkeit, den Commit-Verlauf sauber zu halten. Vermeiden Sie die Verwendung von Zusammenführungen und vermeiden Sie das Erstellen von Zusammenführungskonflikten. Wenn Sie gerrit verwenden, setzen Sie ein Projekt bei Bedarf auf Zusammenführen und ein Projekt auf den Cherry-Pick-Modus und versuchen Sie es selbst.

Nagaraj Magadum
quelle
überhaupt nicht klar, wie dies die Frage beantwortet, vielleicht würden einige Beispiele etwas Licht bringen.
Adrian Nasui
1
Die Tatsache, dass Ihre Geschichte gerade aussehen würde, bedeutet nicht, dass es einfacher zu verstehen wäre.
nicolimo86
Das Zusammenführen ist der übliche Weg, um eine saubere Geschichte zu haben. Cherry-Pick and Rebase wird hauptsächlich in Situationen verwendet, in denen Sie den Verlauf ändern müssen. Was bedeutet, dass das Zusammenführen immer die erste Wahl sein sollte. Ursache Rebase geändert Comit sha`s, was sehr gefährlich ist, wenn Sie mit Fernbedienungen und mehreren Personen arbeiten.
Radon8472
Dieser Typ hier verdient eine Medaille. Er weiß, dass er weiterhin herabgestimmt wird, aber es ist die richtige Antwort. Ein großes Lob.
PW Kad
Entschuldigung, ich habe diese Kommentare bis jetzt nicht gesehen. Bitte probieren Sie es in Ihrer Testumgebung aus, bevor Sie abschließen, und tun Sie, was für Sie funktioniert! Ich habe ungefähr 600 Entwickler, die zu mehreren Produktzweigen beitragen. Es ist mir egal, was Entwickler in ihrem lokalen Arbeitsbereich tun. Wenn eine Änderung zur Integration eingereicht wird, sollte sie in der Lage sein, einen Zweig zu entwickeln oder manchmal einen Zweig zu veröffentlichen oder Fehler zu beheben. Zu Ihrer Information ... Ich benutze Gerrit.
Nagaraj Magadum