Typischerweise ist der Grund, warum Sie eine Festschreibung herauspicken ist eine leicht verändert, um versions in der Tat, wenn Sie machen ein Bit für Bit genau um die gleiche kopieren Sie bekommen nur die Original-commit ID zurück, da der Hash der gleichen Menge von Eingabebits den gleichen Wert hat. Bei einem Cherry-Picked Commit haben Sie jedoch normalerweise einen etwas anderen Quellbaum und haben fast immer eine andere Eltern-ID.
Betrachten Sie dieses Beispiel begehen (immer so leicht modifiziert, Spam-E-Mail-Scanner zu besiegen):
Jetzt, wo ich das diff habe ich das diff als Patch einige andere begehen überprüfen können, anwenden und ein neues aus dem Ergebnis, erneut mit der Log-Nachricht begehen machen. Ich werde ein neues Commit, mit der gleichen Protokollmeldung und dem gleichen Effekt auf Datei distributed.tex
, aber (wahrscheinlich) anders tree
und (definitiv) anders parent
, und einen neuen Committer-Zeitstempel und damit einen anderen Hash.
Das ist eine einzige Auswahl: Vergleichen Sie ein Commit mit seinem Parent (um es in ein Changeset zu konvertieren), wenden Sie diese Änderung woanders an und machen Sie ein neues Commit vom Ergebnis. Angenommen, wir diese Operation für eine Kette von Commits wiederholen :
... <- B3 <- B4 <- B5 <-- branch-X
\
F6 <- F7 <- F8 <-- feature-Y
Lassen Sie uns sagen, dass wir F6
durch F8
kopieren. Rufen Sie die Kopie von F6
, F6'
an, um sie vom Original zu unterscheiden. Machen Sie den Eltern von F6'
B5
sein, und die Eltern von F7'
sein F6'
, und die Eltern von F8'
F7'
sein, so dass wir erhalten:
F6' <- F7' <- F8'
/
... <- B3 <- B4 <- B5 <-- branch-X
\
F6 <- F7 <- F8 <-- feature-Y
ist eine letzte, was wir nun tun. Lassen Sie uns das Etikett feature-Y
, entfernen Sie die aktuell begehen F8
stecken, und fügen Sie ihn auf F8'
statt.
F6' <- F7' <- F8' <-- feature-Y
/
... <- B3 <- B4 <- B5 <-- branch-X
\
F6 <- F7 <- F8 [abandoned]
Et voila, haben wir gerade umbasiert-d.h, -einige Commits kopiert, die auf feature-Y
waren. Die neuen Kopien befinden sich jetzt auf dem Zweig feature-Y
(während des Kopiervorgangs waren sie auf keine Zweig, oder besser, auf die spezielle anonyme Zweig, den Sie haben, wenn Sie im "abgetrennten HEAD" -Modus sind) und die Originalkopien sind ... gut , noch da.
Ich markierte sie hier [verlassen], aber wenn es andere Astes an Etiketten, die Sie F8
verpflichten lassen finden, werden Sie noch in der Lage sein, alle Original-Commits zu sehen. Der Befehl git rebase
verschiebt das feature-Y
-Label, aber nicht, um zu sehen, ob ein anderes Label die Commits sichtbar hält.
bearbeiten: Das gleiche gilt, wenn einige der kopierten-und-dann-aufgegeben Commits über eine Zusammenführung sichtbar sind begehen, zum Beispiel:
F6' <- F7' <- F8' <-- feature-Y
/
.... <- B3 <- B4 <- B5 <-- branch-X
\ \
\ F6 <- F7 <- F8 [abandoned]
\ \
C2 <--- C3 <-- C4 <-- branch-C
Hier branch-C
macht begeht C2
durch C4
sichtbar, aber C4
ist ein Merge-Commit, das F8
sichtbar macht. So jetzt beide F8
(über C4
von branch-C
) und F8'
(über feature-Y
) wird angezeigt, wenn Sie das Repository durchsuchen.
Diese Art der Sache steuert, wann und warum Sie sollten oder nicht umbasen sollten. Seit Rebase Kopien verpflichtet, müssen Sie eines von zwei Dingen sicher sein: dass die Originale wirklich aufgegeben werden, oder dass es in Ordnung ist, die Originale an anderer Stelle zu erhalten. [Bearbeiten beenden.]
Die andere Sache, dass git rebase
automatisiert für Sie ist die Wahl, die zu kopieren verpflichtet. Warum haben wir uns entschieden, F6
durch F8
zu kopieren? Warum diese drei einschließen und alle anderen ausschließen? Dies ist, wo die Argumente zu git rebase
in kommen die jetzt auf diesen Vorschlag Lassen zurückkehren.
git rebase --onto master qc branch
Dies ist die vollständig angegebene Form git rebase
. Das allerletzte Argument, , macht git rebase
in diesem Fall git checkout branch
. Das heißt, das zusätzliche Argument wird einfach an git checkout
übergeben. Danach kann das zusätzliche Argument nicht mehr verwendet werden, also könnten wir folgendes tun:
stattdessen.
Der --onto commit
Teil des Befehls gibt an, wo die Kopien gehen. Genauer gesagt, kopierten wir F6
zu F6'
mit seinem neuen Elternteil B5
. Wenn Sie --onto
verwenden, geben Sie dieses Ziel-Commit an. (Einen Zweignamen verwenden, in diesem Fall master
, bedeutet nur, um die Spitze zu verwenden begeht an diesem Zweig.)
Die ein Argument bleibt, gc
in unserem Fall ist das, was git rebase
Anrufe <upstream>
.
Wenn wir das täten nicht--onto
angeben, das <upstream>
Argument würde zwei Rollen hat: es das Ziel verpflichten nennen würde, und es würde git rebase
die Identität eines verpflichten, dass es sollte speziell nicht Kopie (und dann nicht kopieren noch mehr Commits, basierend auf dieser ID). Wenn wir jedoch --onto
verwenden, haben wir bereits das Ziel-Commit angegeben, sodass das verbleibende Argument nur noch eine Rolle hat: Commits angeben, um das Kopieren zu vermeiden.
Die Art und Weise, wie dieses "Commits to Copy vermeiden" -Ding funktioniert, kann ein bisschen schwierig sein, sich den Kopf zu wickeln. Wir spezifizieren eine insbesondere commit, aber Rebase verwendet hier einen Trick, den git selbst ständig benutzt.Wenn wir git verweisen auf einige begehen, können wir sie fragen bei nur suchen, die zu begehen:
$ git rev-parse c96a
c96af44caf036cf9f04d77c6146086a4ee422ceb
oder wir können sie bitten, schaut euch das an begehen und alle seine Eltern verpflichtet (auch bekannt als seine Abstammung):
$ git rev-list c96a
c96af44caf036cf9f04d77c6146086a4ee422ceb
bca8213e6fda6fdf92b3a5fbc4ee59f755e04a9c
86ac01b3e1d771033e93af93366ace1b586d7c74
bc3fa7a3571231e334f6f06e5610e04227ef1f0b
(rev-parse
tut das ein Commit Sache während rev-list
die Abstammung Variante standardmäßig der Fall ist, obwohl rev-list
enorm flexibel und ist im Herzen oder zumindest die Leber oder Milz-von vielen Git-Befehlen).
Git rebase
wählt sein <upstream>
Argument mit Abstammung Commits zu bekommen, um ausschließen, während der aktuelle Zweig Auswahl (nach der Überprüfung heraus, wenn Sie ihnen geben, dass ein zusätzliches Argument) mit Abstammung Commits zu bekommen, um umfassen. Was immer bleibt, nachdem die Ausschlussgruppe ausgeschlossen wurde, sind die zu kopierenden Commits.
Mit der --onto
Formularfreigaben <upstream>
von seiner Doppeltätigkeitsrolle, so dass Sie selektiver sein können, wenn Sie entscheiden, welche Zusagen zu vermeiden, zu kopieren. Sie werden immer noch Commits kopieren, mit allem was dazu gehört. Insbesondere, wenn Sie Rebase zu kopieren (und dann vergessen Sie die Originale von) Commits, die andere Leute verwenden, müssen sie auch jede Arbeit, die sie getan haben, dass Rebben auf die Originale.
Ich bemerkte, dass die Kopien nur passieren, wenn die Commits in einem anderen Zweig zusammengeführt wurden; nicht zusammengefügte Zweige würden ohne Kopieren reBasen. –
Sie werden immer noch kopiert. Was mit dem Merge-Fall passiert ist, dass * die Originale noch erreichbar sind *, diesmal nicht von einem Branch-Namen, sondern von dem Merge-Commit. Ich füge ein Beispiel mit einer Zusammenführung hinzu. – torek