Beachten Sie, dass dies git rebaseeinen anderen Job hat als git merge(mit oder ohne --ff-only). Sie rebasemüssen vorhandene Commits übernehmen und kopieren . Nehmen wir zum Beispiel an, Sie sind eingeschaltet branch1und haben zwei Commits durchgeführt Aund B:
...-o--o--A--B <-- HEAD=branch1
\
o--C <-- branch2
und Sie entscheiden, dass diese beiden Commits lieber aktiviert werden sollen branch2. Sie können:
- Erhalten Sie eine Liste der Änderungen, die Sie vorgenommen haben
A(Unterschied zu Aden übergeordneten Elementen ).
- Holen Sie sich eine Liste der Änderungen, die Sie vorgenommen haben
B(diff Bgegen A)
- wechseln zu
branch2
- Nehmen Sie die gleichen Änderungen vor, die Sie vorgenommen haben,
Aund übernehmen Sie sie, indem Sie Ihre Festschreibungsnachricht von kopieren A. Nennen wir dieses CommitA'
- Nehmen Sie dann dieselben Änderungen vor, die Sie vorgenommen haben,
Bund schreiben Sie sie fest, indem Sie Ihre Festschreibungsnachricht von kopieren B. Nennen wir das B'.
Es gibt einen git-Befehl, der dieses Diff-and-Then-Copy-and-Commit für Sie ausführt : git cherry-pick. Damit:
git checkout branch2 # switch HEAD to branch2 (commit C)
git cherry-pick branch1^ # this copies A to A'
git cherry-pick branch1 # and this copies B to B'
Jetzt haben Sie Folgendes:
...-o--o--A--B <-- branch1
\
o--C--A'-B' <-- HEAD=branch2
Jetzt können Sie zurück zu branch1Ihrem Original wechseln und es löschen Aund Bmit git reset(ich werde es --hardhier verwenden, ist es auf diese Weise bequemer, da es auch den Arbeitsbaum bereinigt):
git checkout branch1
git reset --hard HEAD~2
Dadurch wird das Original Aund B, 1 so jetzt haben Sie:
...-o--o <-- HEAD=branch1
\
o--C--A'-B' <-- branch2
Jetzt müssen Sie nur noch einmal auschecken, um dort branch2weiterarbeiten zu können.
Dies ist, was git rebasebewirkt: Es "verschiebt" Commits (allerdings nicht, indem es sie tatsächlich verschiebt, weil es nicht möglich ist: In git kann ein Commit niemals geändert werden. Selbst wenn Sie nur die übergeordnete ID ändern, müssen Sie sie in eine neue und etwas andere kopieren verpflichten).
Mit anderen Worten, während git cherry-pickes sich um ein automatisiertes Diff-and-Redo eines Commits handelt, git rebasehandelt es sich um einen automatisierten Prozess zum Wiederherstellen mehrerer Commits und zum Verschieben von Beschriftungen, um die Originale zu "vergessen" oder zu verbergen.
Das Obige zeigt das Verschieben von Commits von einem lokalen Zweig branch1in einen anderen lokalen Zweig branch2, aber git verwendet genau den gleichen Prozess , um Commits zu verschieben, wenn Sie einen Remote-Tracking-Zweig haben, der einige neue Commits erhält, wenn Sie einen ausführen git fetch(einschließlich fetchdes ersten Schritts von git pull). Sie können zunächst an einem Zweig arbeiten feature, der einen Upstream von hat origin/feature, und einige eigene Commits vornehmen:
...-o <-- origin/feature
\
A--B <-- HEAD=feature
Aber dann entscheidest du, dass du sehen sollst, was stromaufwärts passiert ist, also rennst du git fetch, 2 und aha, jemand stromaufwärts hat ein Commit geschrieben C:
...-o--C <-- origin/feature
\
A--B <-- HEAD=feature
An dieser Stelle können Sie einfach Ihre rebase feature‚s Aund Bauf C, geben:
...-o--C <-- origin/feature
\
A'-B' <-- HEAD=feature
Dies sind Kopien Ihres Originals Aund Bdie Originale werden nach Abschluss der Kopien weggeworfen (siehe jedoch Fußnote 1).
Manchmal gibt es nichts zu widerlegen, dh keine Arbeit, die Sie selbst geleistet haben. Das heißt, die Grafik vor dem fetchsieht folgendermaßen aus:
...-o <-- origin/feature
`-- HEAD=feature
Wenn Sie dann git fetchund Commit Ceingehen, bleibt Ihr feature Zweig auf dem alten Commit, während Sie origin/featurevorwärts gegangen sind :
...-o--C <-- origin/feature
`---- <-- HEAD=feature
Dies ist , wo git merge --ff-onlykommt in: Wenn Sie fragen Sie Ihren aktuellen Zweig verschmelzen featuremit origin/feature, git sieht , dass es möglich ist , nur nach vorne auf den Pfeil schieben, wie es war, so dass featurePunkte direkt zu begehen C. Es ist keine tatsächliche Zusammenführung erforderlich.
Wenn Sie Ihre eigenen Commits hätten Aund BSie darum gebeten hätten, diese zusammenzuführen C, würde git eine echte Zusammenführung durchführen und ein neues Zusammenführungs-Commit durchführen M:
...-o--C <-- origin/feature
\ `-_
A--B--M <-- feature
Hier --ff-onlywird angehalten und Sie erhalten einen Fehler. Fütterungsmaterial, auf der anderen Seite, kopiert Aund Bzu A'und B'dann das Original verstecken , Aund B.
Kurz gesagt (ok, zu spät :-)) machen sie einfach verschiedene Dinge. Manchmal ist das Ergebnis das gleiche und manchmal nicht. Wenn es in Ordnung ist, Aund zu kopieren B, können Sie verwenden git rebase; Wenn es jedoch einen guten Grund gibt, sie nicht zu kopieren, können Sie sie git mergemöglicherweise verwenden --ff-only, um sie nach Bedarf zusammenzuführen oder fehlzuschlagen.
1 Git bewahrt die Originale tatsächlich einige Zeit auf - in diesem Fall normalerweise einen Monat -, versteckt sie jedoch. Der einfachste Weg, sie zu finden, sind die "Reflogs" von git, die HEADvor jeder Änderung, die den Zweig und / oder aktualisiert hat , einen Verlauf darüber führen, wohin und wo jeder Zweig zeigte HEAD.
Schließlich werden die reflog History - Einträge verfallen, an welcher Stelle diese Commits für in Frage kommende werden Garbage Collection .
2 Sie können auch git pullein praktisches Skript verwenden , das zunächst ausgeführt wird git fetch. Sobald der Abruf abgeschlossen ist, wird das Convenience-Skript entweder git mergeoder ausgeführt git rebase, je nachdem, wie Sie es konfigurieren und ausführen.