Was bedeutet es, mit Git ein Commit auszuwählen?


2339

Vor kurzem wurde ich zu cherry-pickeinem Commit aufgefordert .

Was bedeutet es also, ein Commit in Git zu pflücken? Wie machst du das?


13
Anstatt zusammenzuführen, ist das erneute Festschreiben von Kirschpflücken von einem Zweig zum Zielzweig (z. B. Master) einfacher.
Levent Divilioglu

Antworten:


2858

Cherry Picking in Git bedeutet, ein Commit aus einem Zweig auszuwählen und auf einen anderen anzuwenden.

Dies steht im Gegensatz zu anderen Methoden wie mergeund, rebasedie normalerweise viele Commits auf einen anderen Zweig anwenden.

  1. Stellen Sie sicher, dass Sie sich in dem Zweig befinden, auf den Sie das Commit anwenden möchten.

    git checkout master
    
  2. Führen Sie Folgendes aus:

    git cherry-pick <commit-hash>
    

NB:

  1. Wenn Sie aus einer öffentlichen Filiale auswählen, sollten Sie die Verwendung in Betracht ziehen

    git cherry-pick -x <commit-hash>
    

    Dadurch wird eine standardisierte Festschreibungsnachricht generiert. Auf diese Weise können Sie (und Ihre Mitarbeiter) weiterhin den Ursprung des Commits verfolgen und künftige Zusammenführungskonflikte vermeiden.

  2. Wenn Sie dem Commit Notizen beigefügt haben, folgen diese nicht dem Cherry-Pick. Um sie auch zu bringen, müssen Sie verwenden:

    git notes copy <from> <to>
    

Zusätzliche Links:


247
Wenn Sie aus einer öffentlichen Filiale auswählen, sollten Sie die Verwendung in Betracht ziehen git cherry-pick -x <commit-hash>. Dadurch wird eine standardisierte Festschreibungsnachricht generiert. Auf diese Weise können Sie (und Ihre Mitarbeiter) weiterhin den Ursprung des Commits verfolgen und künftige Zusammenführungskonflikte vermeiden.
MBober

2
Ist Kirschernte wirklich notwendig? Wird ein gemischter Reset oder ein Soft-Reset nicht einen ähnlichen Job machen?
Nav

10
Beachten Sie, dass Notizen, die dem Commit beigefügt sind, nicht dem Cherry-Pick folgen. Sie müssen verwenden git notes copy <from> <to>, um sie auch zu bringen.
Zitrax

5
Git Push ist der letzte Schritt, um Änderungen am Master vorzunehmen
fühlen Sie sich gut und programmieren Sie am

58
Zu Ihrer Information: Ein Commit enthält semantisch alle Dateien des Arbeitsbaums dieses Augenblicks (und den Commit-Hash des vorherigen Commits), sodass Sie nicht ein ganzes Commit auf ein anderes Commit anwenden, sondern die Änderungen, die ein Commit am vorherigen Commit "cherry-pick commit applies the changes introduced by the named commit on the current branch"Most vorgenommen hat ppl neigen dazu, Commit als Änderungen zu betrachten (wie svn was iirc war), aber es ist nicht so, dass sich jedes Commit auf den vollständigen Arbeitsbaum bezieht. Obwohl dies in diesem Fall keinen Unterschied macht, kann es helfen zu verstehen, warum Git so funktioniert.
Emile Vrijdags

314

Dieses Zitat stammt aus; Versionskontrolle mit Git (Wirklich tolles Buch, ich empfehle Ihnen, es zu kaufen, wenn Sie an Git interessiert sind)

Bearbeiten: Da diese Antwort immer noch Eindruck macht, möchte ich ein sehr schönes Video-Tutorial dazu hinzufügen:

Youtube: Einführung in Git Cherry-Pick

Verwenden von git cherry-pick Der Befehl git cherry-pick commit wendet die Änderungen an, die durch das benannte Commit auf den aktuellen Zweig eingeführt wurden. Es wird ein neues, eindeutiges Commit eingeführt. Genau genommen ändert die Verwendung von Git Cherry-Pick nichts an der vorhandenen Historie in einem Repository. Stattdessen wird der Verlauf erweitert. Wie bei anderen Git-Vorgängen, die Änderungen über das Anwenden eines Diff einführen, müssen Sie möglicherweise Konflikte lösen, um die Änderungen aus dem angegebenen Commit vollständig anzuwenden . Der Befehl git cherry-pick wird normalerweise verwendet, um bestimmte Commits von einem Zweig innerhalb eines Repositorys in einen anderen Zweig einzuführen. Eine häufige Verwendung ist das Vorwärts- oder Rückwärtsportieren von Commits von einem Wartungszweig zu einem Entwicklungszweig.

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, above

Vor: Vor

nach: nach


12
wenn von Kirschen gepflückte Commits auf einem Zweig (b1) genommen und später an den Meister geliefert werden. Und wenn Zweig b1 (von dem ursprünglich Commits ausgewählt wurden) ebenfalls versucht wird, an den Master geliefert zu werden. Wie wäre es mit den Konflikten? Ist das erledigt oder wie funktioniert es?
Parasrish

3
@parasrish Ja, sie wurden bereits bei Ihren vorherigen Zusammenführungen berücksichtigt. Sie haben also a, b, c, d vom Zweig (b1) geändert. Sie Kirsche nur "c" gepflückt. Sobald Sie in Zukunft von (b1) zu Master zusammenführen, werden "c" -Änderungen nur a, b, d zusammengeführt und bleiben "c" -Änderungen, da "c" -Änderungen gleich sind. Wenn Sie jedoch Ihre Zusammenführung zurücksetzen, werden Sie die Änderungen mit "c" zurücksetzen. Sie müssen sie separat zurückrollen.
Teoman Shipahi

12
Es sollte betont werden: In dem gegebenen Beispiel wird nur die Differenz (F - E) auf Z angewendet. Das ist ein enger Fall. Cherry-Pick kann verwendet werden, um die Unterschiede mehrerer Commits anzuwenden, beispielsweise alle Unterschiede zwischen zwei nicht benachbarten Commits. Zum Beispiel folgt von oben (F - E), (E - D), (D - C) und (C - B). Dies entspricht der Anwendung der Differenz (F - B).
Thomas Bitonti

2
Was passiert auch, wenn das ausgewählte Commit (im Beispiel F) mehr als einen unmittelbaren Vorgänger hat?
Thomas Bitonti

2
@ j2emanue Mit anderen Worten, Cherry-Pick nimmt nur Änderungen des letzten Commits entgegen. Wenn Sie 3 verschiedene Male festschreiben und die letzte auswählen, werden beim ersten und zweiten Festschreiben keine Änderungen vorgenommen. Der Befehl Zusammenführen übernimmt alle Ihre Änderungen und gilt für Ihren Zielzweig (Hauptzweig).
Teoman Shipahi

157

Cherry Picking in Git wurde entwickelt, um ein Commit von einem Zweig auf einen anderen Zweig anzuwenden. Es kann getan werden, wenn Sie z. einen Fehler gemacht und eine Änderung in einen falschen Zweig begangen haben, aber nicht den gesamten Zweig zusammenführen möchten. Sie können nur zB. Setzen Sie das Commit zurück und wählen Sie es in einem anderen Zweig aus.

Um es zu verwenden, brauchen Sie nur git cherry-pick hash, wo hashsich ein Commit-Hash von einem anderen Zweig befindet.

Das vollständige Verfahren finden Sie unter: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html


96

Kurzes Beispiel für eine Situation, in der Sie Kirschbaum brauchen

Betrachten Sie das folgende Szenario. Sie haben zwei Zweige.

a) release1 - Dieser Zweig geht an Ihren Kunden, es müssen jedoch noch einige Fehler behoben werden.

b) master - Klassischer Master-Zweig, in dem Sie beispielsweise Funktionen für Release2 hinzufügen können.

JETZT : Sie reparieren etwas in Release1 . Natürlich brauchen Sie diesen Fix auch im Master . Und das ist ein typischer Anwendungsfall für die Kirschernte. Cherry Pick in diesem Szenario bedeutet also, dass Sie ein Commit aus dem Release1- Zweig übernehmen und in den Master- Zweig aufnehmen.


3
Möglicherweise brauchen Sie nur den anderen Weg. Sie haben einen Fehler in Master behoben und sollten diesen für Release1 auswählen. Auch könnten sie eher Repositories als Zweige sein
canbax

1
Warum nicht Merge dafür verwenden?
FreeLightman

Ich würde: Verzweigungsfreigabe erstellen, in der Verzweigung reparieren, Verzweigung in Freigabe zusammenführen, Freigabe in Master zusammenführen.
Jasper-M

57

Cherry-Pick ist eine Git-Funktion. Wenn jemand bestimmte Commits in einem Zweig für einen Zielzweig festschreiben möchte, wird Cherry-Pick verwendet.
Git Cherry-Pick-Schritte sind wie folgt.

  1. Checkout (Wechsel zu) Zielzweig.
  2. git cherry-pick <commit id>
    

    Hier ist die Festschreibungs-ID die Aktivitäts-ID eines anderen Zweigs.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. Zum Zielzweig drücken

Besuchen Sie https://git-scm.com/docs/git-cherry-pick


43

Ich habe Schritt für Schritt Illustrationen vorbereitet, was Cherry-Pick macht - und eine Animation dieser Illustrationen (gegen Ende).

  1. Vor dem Kirschpflücken
    (wir werden ein Kirschpflücken des Commits Laus der Filiale machen feature): Geben Sie hier die Bildbeschreibung ein

  1. Starten des Befehls git cherry-pick feature~2
    ( feature~2ist das 2. Festschreiben vor
    feature, dh das Festschreiben L): Geben Sie hier die Bildbeschreibung ein

  1. Nach dem Ausführen des Befehls ( git cherry-pick feature~2): Geben Sie hier die Bildbeschreibung ein

Das gleiche animierte: Geben Sie hier die Bildbeschreibung ein


Hinweis:

Das Commit L'ist aus Sicht des Benutzers (Commit = Snapshot) die genaue Kopie des Commits L.

Technisch (intern) handelt es sich um ein neues, anderes Commit (da z. B. Lein Zeiger auf K(als übergeordnetes Element) und ein Zeiger auf ( L'enthält E).


Bedeutet das, dass L 'auf dem Zweigmaster N -> M -> L sein wird? oder es wird ausschließlich Commit L auf den Hauptzweig bringen
Priyank Thakkar

1
@PriyankThakkar, ja, ausschließlich L , sonst nichts (wie Sie aus Bildern / Animationen sehen können).
MarianD

22

Sie können sich vorstellen, ob ein Kirschpickel einem Rebase ähnelt oder eher wie ein Rebase verwaltet wird. Damit meine ich, dass ein vorhandenes Commit verwendet und neu generiert wird, wobei als Ausgangspunkt der Leiter des Zweigs verwendet wird, in dem Sie sich gerade befinden.

A rebasenimmt ein Commit mit einem übergeordneten X und generiert das Commit neu, als hätte es tatsächlich ein übergeordnetes Y, und genau das cherry-picktut a.

Bei Cherry Pick geht es mehr darum, wie Sie die Commits auswählen. Mit pull(rebase) regeneriert git implizit Ihre lokalen Commits zusätzlich zu dem, was in Ihren Zweig gezogen wird. cherry-pickWählen Sie jedoch explizit einige Commits aus und generieren Sie sie implizit über Ihrem aktuellen Zweig neu.

Die Art und Weise, wie Sie es tun, ist also unterschiedlich, aber unter der Haube sind sie sehr ähnliche Vorgänge - die Regeneration von Commits.


1
Ich finde das eine sehr hilfreiche Sicht der Dinge. Dies impliziert, warum cherry-picksich das Verhalten so verhält, wenn der Zielzweig später wieder mit dem Quellzweig zusammengeführt wird. Danke mein Herr.
Aluan Haddad

3
Ich möchte Cherry Pick anstelle von Git Merge verwenden, nachdem ein Feature fertig ist. Jeder führt git merge feature_branch immer dann aus, wenn er ein Feature abgeschlossen hat. Warum nicht den Cherry-Pick-Befehl verwenden? haben Sie irgendwelche Gedanken, warum die Mühe Commits zerquetschen , wenn ich herauspicken kann?
j2emanue

11

Es ist wie Kopieren (von irgendwoher) und Einfügen (von irgendwoher), aber für bestimmte Commits.

Wenn Sie beispielsweise einen Hotfix durchführen möchten, können Sie die cherry-pickFunktion verwenden.

Tun Sie dies cherry-pickin einem Entwicklungszweig, und mergedieser verpflichtet sich zu einem Release-Zweig. Führen Sie ebenfalls einen cherry-pickvon einem Release-Zweig zum Master aus. Voila


11

Wenn Sie mit einem Entwicklerteam an einem Projekt arbeiten, kann das Verwalten der Änderungen zwischen mehreren Git-Zweigen zu einer komplexen Aufgabe werden. Manchmal möchten Sie nicht einen ganzen Zweig in einen anderen zusammenführen und müssen nur ein oder zwei bestimmte Commits auswählen. Dieser Vorgang wird als "Kirschernte" bezeichnet.

Sie haben einen großartigen Artikel zum Thema Kirschernte gefunden. Weitere Informationen finden Sie unter: https://www.previousnext.com.au/blog/intro-cherry-picking-git


7

Wenn Sie ohne Festschreibungs-IDs zusammenführen möchten, können Sie diesen Befehl verwenden

git cherry-pick master~2 master~0

Mit dem obigen Befehl werden die letzten drei Commits des Masters von 1 bis 3 zusammengeführt

Wenn Sie dies für ein einzelnes Commit tun möchten, entfernen Sie einfach die letzte Option

git cherry-pick master~2

Auf diese Weise führen Sie das dritte Commit ab dem Ende des Masters zusammen.


Das ist verwirrend. Ich denke, hier bist du in einem anderen Zweig als dem Meister, oder? Und wenn Sie zwei Commits erwähnt haben, beziehen Sie sich auf die Commits <from> und <to>, um den Bereich zu definieren, den Sie auswählen möchten. Richtig? Es wäre sehr hilfreich, wenn das Szenario beschrieben würde. Gute Ergänzung. Vielen Dank.
Saurabh Patil

6

Es wird ein bestimmtes Commit auf Ihre aktuelle Niederlassung angewendet.

Das heisst :

  • Alle durch dieses Commit hinzugefügten Dateien werden hinzugefügt
  • Alle durch dieses Commit gelöschten Dateien werden gelöscht
  • Alle durch dieses Commit geänderten Dateien werden zusammengeführt. Dies bedeutet, dass die gesamte Datei aus dem Commit stammt, nicht nur die Änderungen aus diesem Commit!

Beispiel: Betrachten Sie Commit A.

added newFileA
modified main:
+ import './newFileA'

begehen B.

added newFileB
modified main:
+ import './newFileB'

Wenn Sie Commit B für einen anderen Zweig auswählen , erhalten Sie Folgendes:

/newFileB
/main :
   import './newFileA'
   import './newFileB'

Da Commit B newFileB und main enthält , aber kein newFileA , was zu einem Fehler führt, sollten Sie es mit Vorsicht verwenden.


0

Auszug aus den offiziellen Dokumenten:

Wenden Sie bei einem oder mehreren vorhandenen Commits die jeweils vorgenommene Änderung an und zeichnen Sie für jedes ein neues Commit auf. Dies setzt voraus, dass Ihr Arbeitsbaum sauber ist (keine Änderungen durch das HEAD-Commit).

Wenn nicht klar ist, wie eine Änderung angewendet werden soll, geschieht Folgendes:

  1. Der aktuelle Zweig und der HEAD-Zeiger bleiben beim letzten erfolgreich durchgeführten Commit.

  2. Die CHERRY_PICK_HEAD-Referenz zeigt auf das Commit, das die Änderung eingeführt hat, die schwer anzuwenden ist.

  3. Pfade, in denen die Änderung sauber angewendet wurde, werden sowohl in der Indexdatei als auch in Ihrem Arbeitsbaum aktualisiert.

  4. Bei widersprüchlichen Pfaden zeichnet die Indexdatei bis zu drei Versionen auf, wie im Abschnitt "TRUE MERGE" von git-merge beschrieben. Die Arbeitsbaumdateien enthalten eine Beschreibung des Konflikts in Klammern mit den üblichen Konfliktmarkierungen <<<<<<< und >>>>>>>.

Es werden keine weiteren Änderungen vorgenommen.

Weiterlesen...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.