Ich habe festgestellt, dass die beiden Blöcke der folgenden Git-Befehle unterschiedliche Verhaltensweisen haben, und ich verstehe nicht, warum.
Ich habe einen A
und einen B
Zweig, der von einem abweichtcommit
---COMMIT--- (A)
\
--- (B)
Ich möchte den B
Zweig auf den letzten zurücksetzen A
(und das Commit auf dem B
Zweig haben).
---COMMIT--- (A)
\
--- (B)
Kein Problem, wenn ich:
checkout B
rebase A
Aber wenn ich es mache:
checkout B
rebase --onto B A
Es funktioniert überhaupt nicht, nichts passiert. Ich verstehe nicht, warum die beiden Verhaltensweisen unterschiedlich sind.
Der Phpstorm Git-Client verwendet die zweite Syntax und scheint mir daher völlig kaputt zu sein. Deshalb frage ich nach diesem Syntaxproblem.
git
git-rebase
Xmanoux
quelle
quelle
Antworten:
tl; dr
Die richtige Syntax, die zusätzlich
B
zurA
Verwendunggit rebase --onto
in Ihrem Fall neu erstellt werden muss, lautet:oder Rebase zusätzlich
B
zuA
dem Commit, das das übergeordnete Element von ist, auf dasB
mitB^
oder verwiesen wirdB~1
.Wenn Sie sich für den Unterschied interessieren
git rebase <branch>
undgit rebase --onto <branch>
weiterlesen.Die Quick: Git Rebase
git rebase <branch>
wird den Zweig, auf den Sie gerade ausgecheckt haben und auf den verwiesen wirdHEAD
, zusätzlich zu dem letzten Commit, das von,<branch>
aber nicht von erreichbar ist, neu startenHEAD
.Dies ist der häufigste Fall einer Neugründung und wahrscheinlich derjenige, der weniger Planung im Voraus erfordert.
In diesem Beispiel
F
undG
sind verpflichtet , die von erreichbar ist ,branch
aber nicht ausHEAD
. Das Sprichwortgit rebase branch
nimmtD
, das ist das erste Commit nach dem Verzweigungspunkt, und setzt es neu (dh ändert sein übergeordnetes Element ) auf das letzte Commit, das von,branch
aber nicht von erreichbarHEAD
istG
.The Precise: git rebase --onto mit 2 Argumenten
git rebase --onto
Ermöglicht das erneute Basieren ab einem bestimmten Commit . Sie erhalten die genaue Kontrolle darüber, was und wo neu basiert wird. Dies ist für Szenarien gedacht, in denen Sie präzise sein müssen.Stellen wir uns zum Beispiel vor, wir müssen
HEAD
genau auf der Grundlage von neuF
startenE
. Wir sind nur daran interessiert,F
in unsere Arbeitsbranche zu kommen, während wir gleichzeitig nicht behalten möchten,D
weil sie einige inkompatible Änderungen enthält.In diesem Fall würden wir sagen
git rebase --onto F D
. Das heisst:Mit anderen Worten, ändern Sie das übergeordnete Element von
E
vonD
nachF
. Die Syntax vongit rebase --onto
ist danngit rebase --onto <newparent> <oldparent>
.Ein weiteres Szenario, in dem dies nützlich ist, besteht darin, dass Sie einige Commits schnell aus dem aktuellen Zweig entfernen möchten, ohne eine interaktive Rebase durchführen zu müssen :
In diesem Beispiel würden Sie sagen , um zu entfernen
C
undE
aus der Sequenz zu entfernengit rebase --onto B E
, oderHEAD
auf der Stelle,B
an der sich der alte Elternteil befand , neu zu gründenE
.Der Chirurg: Git Rebase - mit 3 Argumenten
git rebase --onto
kann in Bezug auf Präzision noch einen Schritt weiter gehen. Tatsächlich können Sie einen beliebigen Bereich von Commits auf einen anderen zurücksetzen .Hier ist ein Beispiel:
In diesem Fall möchten wir den genauen Bereich
E---H
über dem Basiswert neu festlegenF
und dabei ignorieren, auf welche StelleHEAD
gerade verwiesen wird. Wir können das tun, indem wir sagengit rebase --onto F D H
, was bedeutet:Die Syntax von
git rebase --onto
mit einer Reihe von Commits wird danngit rebase --onto <newparent> <oldparent> <until>
. Der Trick hier ist die Erinnerung , dass die von referenzierten Festschreibung<until>
ist inbegriffen im Bereich und wird die neu worden ,HEAD
nachdem das Fütterungsmaterial abgeschlossen ist.quelle
<oldparent>
Name bricht zusammen, wenn sich die beiden Teile des Bereichs auf unterschiedlichen Zweigen befinden. Im Allgemeinen heißt es: "Schließen Sie jedes Commit ein, von dem aus Sie erreichbar sind,<until>
aber schließen Sie jedes Commit aus, von dem aus Sie erreichen können<oldparent>
."git rebase --onto <newparent> <oldparent>
ist die beste Erklärung für --onto Verhalten, das ich gesehen habe!--onto
Option, aber das machte es kristallklar! Ich verstehe es nicht einmal so, wie ich es vorher nicht hätte verstehen können: D Danke für das exzellente "Tutorial" :-)Dies ist alles, was Sie wissen müssen, um zu verstehen
--onto
:Sie schalten ein übergeordnetes Element für ein Commit um, geben jedoch nicht das sha des Commits an, sondern nur das sha des aktuellen (alten) übergeordneten Elements.
quelle
Kurz gesagt, gegeben:
Welches ist das gleiche wie (weil
--onto
ein Argument benötigt):Mittel rebase Commits in Bereich (D, H] oben auf F. Hinweis wird der Bereich der linken Hand aus. Es ist exklusiv , weil es einfacher ist , 1. durch Eingabe zB angeben , begehen
branch
zu lassen ,git
die ersten finden weicht von begehenbranch
dhD
was zuH
.OP-Fall
Kann in einen einzelnen Befehl geändert werden:
Was hier wie ein Fehler aussieht, ist die Platzierung,
B
was bedeutet, dass "einige Commits verschoben werden, die zu einer VerzweigungB
überB
" führen. Die Frage ist, was "einige Commits" sind. Wenn Sie ein-i
Flag hinzufügen, sehen Sie, dass es sich um ein einzelnes Commit handelt, auf das gezeigt wirdHEAD
. Das Festschreiben wird übersprungen, da es bereits auf das--onto
Ziel angewendet wirdB
und daher nichts passiert.Der Befehl ist in jedem Fall Unsinn, wenn der Zweigname so wiederholt wird. Dies liegt daran, dass der Bereich der Festschreibungen einige Festschreibungen sind, die sich bereits in diesem Zweig befinden, und während der erneuten Basisung werden alle übersprungen.
Weitere Erklärung und anwendbare Verwendung von
git rebase <upstream> <branch> --onto <newbase>
.git rebase
Standardeinstellungen.Erweitert auf:
Automatisches Auschecken nach Rebase.
Bei normaler Verwendung wie:
Sie werden nicht merken , dass nach Fütterungsmaterial
git
bewegt sichbranch
auf die zuletzt begehen indexiert und hatgit checkout branch
(siehegit reflog
Geschichte). Was interessant ist, wenn das zweite Argument Commit-Hash ist , stattdessen funktioniert die Rebase des Zweignamens immer noch, aber es gibt keinen Zweig zum Verschieben, sodass Sie in "losgelöstem KOPF" landen und stattdessen zum verschobenen Zweig ausgecheckt werden.Lassen Sie primär divergierende Commits aus.
Das
master
In--onto
stammt aus dem 1.git rebase
Argument.So praktisch kann es jedes andere Commit oder jeder andere Zweig sein. Auf diese Weise können Sie die Anzahl der Rebase-Commits begrenzen, indem Sie die neuesten Commits verwenden und primär divergierende Commits belassen.
Wird ein einzelnes Commit zurückweisen, auf das verwiesen wird
HEAD
,master
und in "losgelöstem KOPF" enden.Vermeiden Sie explizite Kassen.
Die Standardeinstellung
HEAD
oder dascurrent_branch
Argument wird kontextabhängig von der Stelle übernommen, an der Sie sich befinden. Aus diesem Grund checken die meisten Benutzer zu einem Zweig aus, den sie neu aufbauen möchten. Wenn das 2. Rebase-Argument explizit angegeben wird, müssen Sie vor dem Rebase nicht auschecken, um es implizit zu übergeben.Dies bedeutet, dass Sie Commits und Zweige von jedem Ort aus neu starten können . Also zusammen mit der automatischen Kaufabwicklung nach dem Rebase. Sie müssen den neu basierten Zweig vor oder nach dem erneuten Basieren nicht separat auschecken.
quelle
Einfach ausgedrückt,
git rebase --onto
wählt eine Reihe von Commits aus und basiert sie auf dem als Parameter angegebenen Commit.Lesen Sie die Manpages für
git rebase
, suchen Sie nach "auf". Die Beispiele sind sehr gut:In diesem Fall weisen Sie git an, die Commits von oben
topicA
nachtopicB
oben neu zu startenmaster
.quelle
Um den Unterschied zwischen
git rebase
und besser zu verstehengit rebase --onto
, ist es gut zu wissen, welche Verhaltensweisen für beide Befehle möglich sind.git rebase
Ermöglichen Sie uns, unsere Commits über den ausgewählten Zweig zu verschieben. Wie hier:und das Ergebnis ist:
git rebase --onto
ist präziser. Es ermöglicht uns, ein bestimmtes Commit auszuwählen, wo wir beginnen und wo wir enden möchten. Wie hier:und das Ergebnis ist:
Um weitere Informationen zu erhalten, empfehle ich Ihnen, meinen eigenen Artikel über git rebase --onto Übersicht zu lesen
quelle
git rebase --onto F D
als gesetztes Kind von Ds Eltern als F lesen , nicht wahr?Dafür
onto
benötigen Sie zwei zusätzliche Filialen. Mit diesem Befehl können Sie Commits anwendenbranchB
, diebranchA
auf einem anderen Zweig basieren, zmaster
. Im folgenden BeispielbranchB
basiert aufbranchA
und Sie möchten die Änderungen vonbranchB
onmaster
anwenden, ohne die Änderungen von anzuwendenbranchA
.mit den Befehlen:
Sie erhalten die folgende Festschreibungshierarchie.
quelle
rebase --onto branchA branchB
würden, würde dies den gesamten Hauptzweig auf den Kopf von Zweig A setzen?checkout branchB: rebase --onto master branchA
?Es gibt einen anderen Fall, der
git rebase --onto
schwer zu verstehen ist: Wenn Sie auf ein Commit zurückgreifen, das sich aus einem symmetrischen Differenzwähler ergibt (die drei Punkte '...
')Git 2.24 (Q4 2019) verwaltet diesen Fall besser:
Siehe Commit 414d924 , Commit 4effc5b , Commit c0efb4c , Commit 2b318aa (27. August 2019) und Commit 793ac7e , Commit 359eceb (25. August 2019) von Denton Liu (
Denton-L
) .Unterstützt von: Eric Sunshine (
sunshineco
) , Junio C. Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) und Johannes Schindelin (dscho
) .Siehe Commit 6330209 , Commit c9efc21 (27. August 2019) und Commit 4336d36 (25. August 2019) von Ævar Arnfjörð Bjarmason (
avar
).Unterstützt von: Eric Sunshine (
sunshineco
) , Junio C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) und Johannes Schindelin (dscho
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 640f9cd , 30. September 2019)Lesen Sie an dieser Stelle " Was sind die Unterschiede zwischen Doppelpunkt-
..
und Dreifachpunkt...
" in Git-Diff-Festschreibungsbereichen? "Hier: „
master...
“ bezieht sich aufmaster...HEAD
, das istB
: HEAD ist Seite HEAD (derzeit ausgecheckt): Sie Rebasing aufB
.Was gründen Sie neu? Jedes Commit, das nicht im Master enthalten ist und vom
side
Zweig aus erreichbar ist : Es gibt nur ein Commit, das zu dieser Beschreibung passt:D
... das bereits oben istB
!Wiederum
rebase --onto
würde ein solches vor Git 2.24 dazu führen,D
dass es immer neu basiert, egal was passiert.Das ist vergleichbar mit dem
rebase --onto B A
der OP, die nichts getan hat.und der fehlerhafte Befehl war
A
rebase --onto C F topic
bedeutet jedes Commit danachF
, das vontopic
HEAD erreicht werden kann: das istG
nur, nicht sichF
selbst.Ein schneller
F
Vorlauf würde in diesem Fall in den neu basierten Zweig einbezogen, was falsch ist.quelle