Seit die Zeit git cherry-pick
gelernt hat, mehrere Commits anwenden zu können, wurde die Unterscheidung zwar etwas umstritten, aber dies ist etwas, das man als konvergente Evolution bezeichnen kann ;-)
Der wahre Unterschied liegt in der ursprünglichen Absicht, beide Werkzeuge zu erstellen:
git rebase
Die Aufgabe besteht darin, eine Reihe von Änderungen, die ein Entwickler in seinem privaten Repository vorgenommen hat und die gegen Version X eines Upstream-Zweigs erstellt wurden, auf Version Y desselben Zweigs (Y> X) weiterzuleiten. Dies ändert effektiv die Basis dieser Reihe von Commits und führt somit zu einer "Umbasierung".
(Es ermöglicht dem Entwickler auch, eine Reihe von Commits auf ein beliebiges Commit zu übertragen, dies ist jedoch weniger offensichtlich.)
git cherry-pick
dient dazu, ein interessantes Engagement von einer Entwicklungslinie in eine andere zu bringen. Ein klassisches Beispiel ist das Backportieren eines Sicherheitsupdates für einen instabilen Entwicklungszweig in einen stabilen (Wartungs-) Zweig, in dem a merge
keinen Sinn ergibt , da dies viele unerwünschte Änderungen mit sich bringen würde.
Seit seinem ersten Erscheinen git cherry-pick
konnten mehrere Commits gleichzeitig ausgewählt werden.
Der wahrscheinlich auffälligste Unterschied zwischen diesen beiden Befehlen besteht darin, wie sie den Zweig behandeln, an dem sie arbeiten: git cherry-pick
Bringt normalerweise ein Commit von einem anderen Ort und wendet es auf Ihren aktuellen Zweig an, zeichnet ein neues Commit auf, git rebase
nimmt Ihren aktuellen Zweig und schreibt ihn neu Eine Reihe eigener Tipps begeht auf die eine oder andere Weise. Ja, dies ist eine stark heruntergekommene Beschreibung dessen, was getan werden git rebase
kann, aber es ist beabsichtigt, zu versuchen, die allgemeine Idee zum Eintauchen zu bringen.
Aktualisieren Sie , um ein Beispiel für die Verwendung git rebase
zu erläutern.
In dieser Situation heißt es im
Buch :
Es gibt jedoch noch einen anderen Weg: Sie können den Patch der in C3 eingeführten Änderung übernehmen und erneut auf C4 anwenden. In Git wird dies als Rebasing bezeichnet. Mit dem Befehl rebase können Sie alle Änderungen, die in einem Zweig festgeschrieben wurden, auf einen anderen übertragen.
In diesem Beispiel würden Sie Folgendes ausführen:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
"Der Haken" hier ist, dass in diesem Beispiel der Zweig "Experiment" (das Thema für die Neubasierung) ursprünglich vom Zweig "Master" abgezweigt wurde und daher die Commits C0 bis C2 mit ihm teilt - effektiv ist "Experiment" " Master "bis einschließlich C2 plus Commit C3 darüber. (Dies ist der einfachste Fall. Natürlich kann "Experiment" mehrere Dutzend Commits zusätzlich zu seiner ursprünglichen Basis enthalten.)
Jetzt git rebase
wird gesagt, dass "Experiment" auf die aktuelle Spitze von "Master" zurückgesetzt werden soll, und es git rebase
geht so:
- Läuft, um
git merge-base
zu sehen, was das letzte Commit ist, das sowohl von "Experiment" als auch von "Master" geteilt wird (was ist der Sinn der Ablenkung, mit anderen Worten). Das ist C2.
- Spart alle seit dem Umleitungspunkt getätigten Commits; In unserem Spielzeugbeispiel ist es nur C3.
- Spult den KOPF zurück (der auf das Spitzen-Commit von "Experiment" zeigt, bevor die Operation ausgeführt wird), um auf die Spitze von "Master" zu zeigen - wir stützen uns darauf.
- Versucht, alle gespeicherten Commits (wie mit
git apply
) der Reihe nach anzuwenden . In unserem Spielzeugbeispiel ist es nur ein Commit, C3. Angenommen, seine Anwendung erzeugt ein Commit C3 '.
- Wenn alles gut gegangen ist, wird die Referenz "Experiment" aktualisiert, um auf das Commit zu verweisen, das sich aus dem Anwenden des zuletzt gespeicherten Commits ergibt (in unserem Fall C3 ').
Nun zurück zu Ihrer Frage. Wie Sie sehen können, wird hier technisch gesehen git rebase
eine Reihe von Commits von "Experiment" bis zur Spitze von "Master" transplantiert, sodass Sie zu Recht feststellen können, dass tatsächlich "ein anderer Zweig" im Prozess ist. Aber das Wesentliche ist, dass das Tip-Commit aus "Experiment" das neue Tip-Commit in "Experiment" war. Es hat nur seine Basis geändert:
Auch hier kann man technisch gesehen feststellen, dass git rebase
hier bestimmte Commits von "master" enthalten sind, und dies ist absolut korrekt.
Mit Cherry-Pick bleiben die ursprünglichen Commits / Zweige erhalten und es werden neue Commits erstellt. Bei der erneuten Basis wird der gesamte Zweig verschoben, wobei der Zweig auf die wiedergegebenen Commits zeigt.
Angenommen, Sie haben begonnen mit:
Rebase:
Du erhältst:
Kirschpickel:
Du erhältst:
Für weitere Informationen über Git hat dieses Buch das meiste davon (http://git-scm.com/book)
quelle
topic
basiertmaster
, enthält es nicht die ausgelassenen Commits. In welchem Zweig werden sie also sein?git checkout topic
und danngit reset --hard C'
nach der Kirschernte, dann haben Sie das gleiche Ergebnis wie nach der Umbasierung. Ich habe mich vor vielen Zusammenführungskonflikten bewahrt, indem ich Kirschen gepflückt habe, weil der gemeinsame Vorfahr schon lange zurückliegt.git
-guru aber dierebase
/cherry-pick
ist auf alle Details mit ,git
dass ich ein Problem hatte Verständnis.git checkout -b
, der nichts damit zu tun hatgit cherry-pick
. Eine bessere Möglichkeit zu erklären, was Sie sagen möchten, wäre: „Sie rennengit rebase
auf demtopic
Ast und passieren ihnmaster
. Sie laufengit cherry-pick
auf demmaster
Ast und übergibst ihn (Commits von)topic
. “Das Pflücken von Kirschen funktioniert für einzelne Commits .
Wenn Sie die Basis neu festlegen, werden alle Commits im Verlauf auf den HEAD des Zweigs angewendet , die dort fehlen.
quelle
git cherry-pick foo~3..foo
und die Tree-Top-Commits von "foo" einzeln auswählen lassen.git am
darauf. Während ein Cherry Pick Commit für Commit anwendet (möglicherweise durch Erstellen eines Postfachs mit einer Nachricht für jeden Patch). Meine Rebase schlug fehl, weil die von ihr erstellte Postfachdatei nicht mehr über genügend Speicherplatz auf dem Laufwerk verfügte, aber Cherry-Pick mit demselben Revisionsbereich erfolgreich war (und anscheinend schneller ausgeführt wird).Eine kurze Antwort:
Die oben gegebenen Antworten sind gut. Ich wollte nur ein Beispiel geben, um ihre Wechselbeziehung zu demonstrieren.
Es wird nicht empfohlen, "git rebase" durch diese Abfolge von Aktionen zu ersetzen. Es handelt sich lediglich um einen "Proof of Concept", der hoffentlich dazu beiträgt, die Funktionsweise der Dinge zu verstehen.
Angesichts des folgenden Spielzeug-Repositorys:
Angenommen, wir haben einige sehr wichtige Änderungen (Commits Nr. 2 bis Nr. 5) im Master, die wir in unsere test_branch_1 aufnehmen möchten. Normalerweise wechseln wir einfach zu einem Zweig und machen "Git Rebase Master". Aber da wir so tun, als wären wir nur mit "git cherry-pick" ausgestattet, tun wir Folgendes:
Nach all diesen Operationen sieht unser Commit-Diagramm folgendermaßen aus:
Wie wir sehen können, wurden die Commits Nr. 6 und Nr. 7 gegen 7254931 angewendet (ein Tipp-Commit des Masters). HEAD wurde verschoben und zeigt auf ein Commit, das im Wesentlichen eine Spitze eines neu basierten Zweigs ist. Jetzt müssen wir nur noch einen alten Verzweigungszeiger löschen und einen neuen erstellen:
test_branch_1 ist jetzt von der letzten Master-Position aus gerootet . Getan!
quelle
cherry-pick
in der Lage ist, eine Reihe von Commits anzuwenden, denke ich, ja. Obwohl dies eine etwas seltsame Art ist, hindert Sie nichts daran, alle Commits in Ihrem Feature-Zweig darübermaster
auszuwählen, den Feature-Zweig zu löschen und neu zu erstellen, sodass er auf die Spitze von zeigtmaster
. Sie können denken,git rebase
der als eine Sequenzgit cherry-pick feature_branch
,git branch -d feature_branch
undgit branch feature_branch master
.Sie sind beide Befehle zum Umschreiben der Commits eines Zweigs über einen anderen: Der Unterschied besteht darin, welcher Zweig - "Ihr" (der aktuell ausgecheckte
HEAD
) oder "ihr" (der Zweig, der als Argument an den Befehl übergeben wurde) - ist die Basis für dieses Umschreiben.git rebase
nimmt ein Ausgang zu begehen und Replays Ihre Commits als nach kommen sie (der Start begehen).git cherry-pick
nimmt eine Reihe von Commits und Replays ihre Commits wie nach kommen Sie (IhreHEAD
).Mit anderen Worten, die beiden Befehle in ihrem Kern Verhalten (ohne Berücksichtigung ihrer unterschiedlichen Leistungsmerkmalen, Aufrufkonventionen und Erweiterungsoptionen), symmetrisch : Zweig Check - out
bar
und Laufgit rebase foo
setzt denbar
Zweig in die gleiche Geschichte wie Check - out Zweigfoo
und läuftgit cherry-pick ..bar
gesetzt würdefoo
bis (die Änderungen vonfoo
, gefolgt von den Änderungen vonbar
).Naming weise kann der Unterschied zwischen den beiden Befehlen in Erinnerung bleiben , dass jeder beschreibt , was es tut , um den aktuellen Zweig:
rebase
macht den anderen Kopf die neue Basis für die Änderungen, währendcherry-pick
Picks aus dem anderen Zweig ändern und legt sie oben auf IhreHEAD
(wie Kirschen auf einem Eisbecher).quelle
Beide machen sehr ähnliche Dinge; Der hauptsächliche konzeptionelle Unterschied besteht (vereinfacht ausgedrückt) darin, dass:
rebase verschiebt Commits vom aktuellen Zweig in einen anderen Zweig .
Cherry-Pick- Kopien werden von einem anderen Zweig in den aktuellen Zweig übernommen .
Verwenden von Diagrammen ähnlich der Antwort von @Kenny Ho :
Angesichts dieses Ausgangszustands:
... und vorausgesetzt, Sie möchten, dass die Commits aus dem
topic
Zweig über dem aktuellenmaster
Zweig wiedergegeben werden, haben Sie zwei Möglichkeiten:Verwenden von rebase: Sie gehen zuerst zu,
topic
indem Sie Folgendes tungit checkout topic
, und verschieben dann den Zweig, indem Sie Folgendes ausführengit rebase master
:Ergebnis: Ihr aktueller Zweig
topic
wurde neu basiert (verschoben)master
.Die
topic
Niederlassung wurde aktualisiert, während diemaster
Niederlassung bestehen blieb.Mit Kirsche-Pick : Sie zuerst gehen würde ,
master
indem Siegit checkout master
und dann den Zweig kopieren , indem Siegit cherry-pick topic~3..topic
(oder äquivalentgit cherry-pick B..G
), die Herstellung von :Ergebnis: die Commits aus
topic
wurden kopiert inmaster
.Das
master
Niederlassung wurde aktualisiert, während dietopic
Niederlassung bestehen blieb.Natürlich musste man Cherry-Pick hier explizit anweisen, eine Folge von Commits unter Verwendung der Bereichsnotation auszuwählen
foo..bar
. Wenn Sie einfach den Filialnamen wie in übergeben hättengit cherry-pick topic
, hätte er nur das Commit an der Spitze der Filiale erfasst, was zu Folgendem geführt hätte:quelle