English ▾ Themen ▾ Neueste Version ▾ git-rebase zuletzt aktualisiert in 2.52.0

NAME

git-rebase - Commits auf einem anderen Basis-Tip neu anwenden

SYNOPSIS

git rebase [-i | --interactive] [<options>] [--exec <cmd>]
	[--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
	--root [<branch>]
git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)

BESCHREIBUNG

Pflanzen Sie eine Serie von Commits auf einen anderen Startpunkt um. Sie können auch git rebase verwenden, um Commits neu zu ordnen oder zu kombinieren: siehe INTERAKTIVER MODUS unten, wie das geht.

Stellen Sie sich zum Beispiel vor, Sie hätten an dem topic-Branch in dieser Historie gearbeitet, und Sie möchten den auf dem master-Branch gemachten Arbeiten "aufholen".

          A---B---C topic
         /
    D---E---F---G master

Sie möchten die Commits, die Sie auf topic gemacht haben, seitdem er von master abgewichen ist (d.h. A, B und C), auf den aktuellen master umpflanzen. Dies können Sie erreichen, indem Sie git rebase master ausführen, während der topic-Branch ausgecheckt ist. Wenn Sie topic umbasen möchten, während Sie sich auf einem anderen Branch befinden, ist git rebase master topic eine Abkürzung für git checkout topic && git rebase master.

                  A'--B'--C' topic
                 /
    D---E---F---G master

Wenn während dieses Prozesses ein Merge-Konflikt auftritt, stoppt git rebase beim ersten problematischen Commit und hinterlässt Konfliktmarker. Wenn dies geschieht, können Sie eine der folgenden Aktionen durchführen:

  1. Beheben Sie den Konflikt. Sie können git diff verwenden, um die Marker (<<<<<<) zu finden und die Datei zur Behebung des Konflikts zu bearbeiten. Für jede bearbeitete Datei müssen Sie Git mitteilen, dass der Konflikt behoben wurde. Sie können den Konflikt mit git add <dateiname> als behoben markieren. Nachdem alle Konflikte behoben sind, können Sie den Rebase-Prozess fortsetzen mit

    git rebase --continue
  2. Brechen Sie den git rebase ab und setzen Sie Ihren Branch mit folgendem Befehl in seinen ursprünglichen Zustand zurück:

    git rebase --abort
  3. Überspringen Sie den Commit, der den Merge-Konflikt verursacht hat, mit

    git rebase --skip

Wenn Sie keinen <upstream> angeben, auf den rebased werden soll, werden die in den Optionen branch.<name>.remote und branch.<name>.merge konfigurierten Upstreams verwendet (siehe git-config[1] für Details), und die Option --fork-point wird angenommen. Wenn Sie sich derzeit auf keinem Branch befinden oder der aktuelle Branch keinen konfigurierten Upstream hat, wird der Rebase abgebrochen.

Hier ist eine vereinfachte Beschreibung dessen, was git rebase <upstream> tut:

  1. Erstellen Sie eine Liste aller Commits auf Ihrem aktuellen Branch seitdem er von <upstream> abzweigte, die keinen entsprechenden Commit in <upstream> haben.

  2. Checken Sie <upstream> mit dem Äquivalent von git checkout --detach <upstream> aus.

  3. Spielen Sie die Commits nacheinander in der richtigen Reihenfolge ab. Dies ähnelt dem Ausführen von git cherry-pick <commit> für jeden Commit. Siehe MERGES REBASEN, wie Merges behandelt werden.

  4. Aktualisieren Sie Ihren Branch so, dass er auf den letzten Commit zeigt, mit dem Äquivalent von git checkout -B <branch>.

Hinweis
Beim Start des Rebase wird ORIG_HEAD so gesetzt, dass er auf den Commit an der Spitze des zu rebasenden Branches zeigt. Allerdings ist nicht garantiert, dass ORIG_HEAD am Ende des Rebase immer noch auf diesen Commit zeigt, wenn andere Befehle, die ORIG_HEAD ändern (wie git reset), während des Rebase verwendet werden. Die vorherige Branch-Spitze ist jedoch über die Reflog des aktuellen Branches zugänglich (d.h. @{1}, siehe gitrevisions[7].

EINEN TOPIC-BRANCH MIT --ONTO UMPFLANZEN

Hier erfahren Sie, wie Sie einen Topic-Branch, der auf einem Branch basiert, auf einen anderen umpflanzen, um so zu tun, als hätten Sie den Topic-Branch von letzterem Branch verzweigt, mithilfe von rebase --onto.

Zuerst nehmen wir an, Ihr topic basiert auf dem Branch next. Zum Beispiel hängt ein in topic entwickelter Feature von Funktionalität ab, die in next zu finden ist.

    o---o---o---o---o  master
         \
          o---o---o---o---o  next
                           \
                            o---o---o  topic

Wir möchten, dass topic von master verzweigt wird; zum Beispiel, weil die Funktionalität, von der topic abhängt, in den stabileren master-Branch gemergt wurde. Wir möchten, dass unser Baum wie folgt aussieht:

    o---o---o---o---o  master
        |            \
        |             o'--o'--o'  topic
         \
          o---o---o---o---o  next

Dies können wir mit dem folgenden Befehl erreichen:

git rebase --onto master next topic

Ein weiteres Beispiel für die --onto-Option ist das Rebasen eines Teils eines Branches. Wenn wir folgende Situation haben:

                            H---I---J topicB
                           /
                  E---F---G  topicA
                 /
    A---B---C---D  master

dann der Befehl

git rebase --onto master topicA topicB

würde dazu führen:

                 H'--I'--J'  topicB
                /
                | E---F---G  topicA
                |/
    A---B---C---D  master

Dies ist nützlich, wenn topicB nicht von topicA abhängt.

Eine Reihe von Commits kann auch mit rebase entfernt werden. Wenn wir folgende Situation haben:

    E---F---G---H---I---J  topicA

dann der Befehl

git rebase --onto topicA~5 topicA~3 topicA

würde dazu führen, dass die Commits F und G entfernt werden.

    E---H'---I'---J'  topicA

Dies ist nützlich, wenn F und G fehlerhaft waren oder nicht Teil von topicA sein sollten. Beachten Sie, dass das Argument für --onto und der <upstream>-Parameter jedes gültige Commit-Objekt sein können.

MODUSOPTIONEN

Die Optionen in diesem Abschnitt können nicht mit anderen Optionen verwendet werden, auch nicht untereinander.

--continue

Setzen Sie den Rebase-Prozess nach der Behebung eines Merge-Konflikts fort.

--skip

Setzen Sie den Rebase-Prozess fort, indem Sie den aktuellen Patch überspringen.

--abort

Brechen Sie die Rebase-Operation ab und setzen Sie HEAD auf den ursprünglichen Branch zurück. Wenn <branch> bei Beginn der Rebase-Operation angegeben wurde, wird HEAD auf <branch> zurückgesetzt. Andernfalls wird HEAD auf den Stand zurückgesetzt, auf dem es sich beim Beginn der Rebase-Operation befand.

--quit

Brechen Sie die Rebase-Operation ab, aber HEAD wird nicht auf den ursprünglichen Branch zurückgesetzt. Der Index und der Arbeitsbaum bleiben ebenfalls unverändert. Wenn ein temporärer Stash-Eintrag mit --autostash erstellt wurde, wird er in der Stash-Liste gespeichert.

--edit-todo

Bearbeiten Sie die Todo-Liste während eines interaktiven Rebase.

--show-current-patch

Zeigen Sie den aktuellen Patch bei einem interaktiven Rebase an oder wenn der Rebase wegen Konflikten gestoppt wurde. Dies ist das Äquivalent zu git show REBASE_HEAD.

OPTIONEN

--onto <newbase>

Startpunkt, an dem die neuen Commits erstellt werden sollen. Wenn die Option --onto nicht angegeben ist, ist der Startpunkt <upstream>. Kann jedes gültige Commit-Objekt sein, nicht nur ein bestehender Branch-Name.

Als Sonderfall können Sie "A...B" als Abkürzung für die Merge-Basis von A und B verwenden, wenn es genau eine Merge-Basis gibt. Sie können höchstens eines von A oder B weglassen, in welchem Fall es standardmäßig HEAD ist.

Siehe EINEN TOPIC-BRANCH MIT --ONTO UMPFLANZEN oben für Beispiele.

--keep-base

Setzen Sie den Startpunkt, an dem die neuen Commits erstellt werden sollen, auf die Merge-Basis von <upstream> und <branch>. Das Ausführen von git rebase --keep-base <upstream> <branch> ist äquivalent zum Ausführen von git rebase --reapply-cherry-picks --no-fork-point --onto <upstream>...<branch> <upstream> <branch>.

Diese Option ist nützlich, wenn man einen Feature-Entwicklung auf einem Upstream-Branch durchführt. Während der Arbeit am Feature kann sich der Upstream-Branch weiterentwickeln, und es ist möglicherweise nicht ratsam, immer weiter auf dem Upstream zu rebasen, sondern die Basis-Commits beizubehalten. Da die Basis-Commits unverändert bleiben, impliziert diese Option --reapply-cherry-picks, um das Verlieren von Commits zu vermeiden.

Obwohl sowohl diese Option als auch --fork-point die Merge-Basis zwischen <upstream> und <branch> finden, verwendet diese Option die Merge-Basis als Startpunkt, auf dem neue Commits erstellt werden, während --fork-point die Merge-Basis verwendet, um die Menge der Commits zu bestimmen, die rebased werden.

Siehe auch INKOMPATIBLE OPTIONEN unten.

<upstream>

Upstream-Branch, mit dem verglichen werden soll. Kann jedes gültige Commit-Objekt sein, nicht nur ein bestehender Branch-Name. Standardmäßig der konfigurierte Upstream für den aktuellen Branch.

<branch>

Arbeitsbranch; standardmäßig HEAD.

--apply

Verwenden Sie Anwendungsstrategien zum Rebasen (Aufruf von git-am intern). Diese Option kann in Zukunft eine No-op werden, sobald das Merge-Backend alles leistet, was das Apply-Backend tut.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--empty=(drop|keep|stop)

Wie mit Commits umgegangen werden soll, die ursprünglich nicht leer waren und keine sauberen Cherry-Picks von Upstream-Commits sind, die aber nach dem Rebasen leer werden (da sie eine Teilmenge bereits vorhandener Upstream-Änderungen enthalten).

drop

Der Commit wird verworfen. Dies ist das Standardverhalten.

keep

Der Commit wird beibehalten. Diese Option wird impliziert, wenn --exec angegeben ist, es sei denn, -i/--interactive ist ebenfalls angegeben.

stop
ask

Der Rebase wird angehalten, wenn der Commit angewendet wird, was Ihnen die Wahl lässt, ob Sie ihn verwerfen, Dateien weiter bearbeiten oder einfach die leeren Änderungen committen möchten. Diese Option wird impliziert, wenn -i/--interactive angegeben ist. ask ist ein veraltetes Synonym für stop.

Beachten Sie, dass Commits, die ursprünglich leer sind, beibehalten werden (es sei denn, --no-keep-empty wird angegeben), und Commits, die saubere Cherry-Picks sind (wie von git log --cherry-mark ... bestimmt), werden als vorbereitender Schritt erkannt und verworfen (es sei denn, --reapply-cherry-picks oder --keep-base wird übergeben).

Siehe auch INKOMPATIBLE OPTIONEN unten.

--no-keep-empty
--keep-empty

Behalten Sie keine Commits, die vor dem Rebase leer sind (d.h. die nichts von ihrem Elternteil ändern), im Ergebnis. Standardmäßig werden Commits, die leer sind, beibehalten, da das Erstellen solcher Commits die Überschreibungsflagge --allow-empty an git commit erfordert, was bedeutet, dass ein Benutzer einen solchen Commit sehr bewusst erstellt und ihn daher behalten möchte.

Die Verwendung dieser Flagge wird wahrscheinlich selten vorkommen, da Sie Commits, die leer sind, einfach durch einen interaktiven Rebase loswerden können, indem Sie die Zeilen entfernen, die den Commits entsprechen, die Sie nicht möchten. Diese Flagge existiert als praktische Abkürzung, z.B. für Fälle, in denen externe Tools viele leere Commits generieren und Sie diese alle entfernen möchten.

Für Commits, die nicht leer sind, aber nach dem Rebasen leer werden, siehe die Option --empty.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--reapply-cherry-picks
--no-reapply-cherry-picks

Wenden Sie alle sauberen Cherry-Picks von Upstream-Commits erneut an, anstatt sie präventiv zu verwerfen. (Wenn diese Commits nach dem Rebasen leer werden, weil sie eine Teilmenge von bereits vorhandenen Upstream-Änderungen enthalten, wird das Verhalten gegenüber ihnen durch die Option --empty gesteuert.)

In Abwesenheit von --keep-base (oder wenn --no-reapply-cherry-picks angegeben wird) werden diese Commits automatisch verworfen. Da dies das Lesen aller Upstream-Commits erfordert, kann dies bei Repositories mit einer großen Anzahl von Upstream-Commits, die gelesen werden müssen, kostspielig sein. Bei Verwendung des merge-Backends werden Warnungen für jeden verworfenen Commit ausgegeben (es sei denn, --quiet ist angegeben). Ratschläge werden ebenfalls ausgegeben, es sei denn, advice.skippedCherryPicks ist auf false gesetzt (siehe git-config[1]).

--reapply-cherry-picks ermöglicht es rebase, das Lesen aller Upstream-Commits zu vermeiden, was die Leistung potenziell verbessern kann.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--allow-empty-message

No-op. Das Rebasen von Commits mit leerer Nachricht schlug früher fehl, und diese Option würde dieses Verhalten überschreiben und das Rebasen von Commits mit leerer Nachricht erlauben. Jetzt verursachen Commits mit leerer Nachricht nicht mehr, dass der Rebase stoppt.

Siehe auch INKOMPATIBLE OPTIONEN unten.

-m
--merge

Verwenden von Merge-Strategien zum Rebasen (Standard).

Beachten Sie, dass ein Rebase-Merge funktioniert, indem jeder Commit vom Arbeitsbranch auf den <upstream>-Branch wiederholt wird. Aus diesem Grund ist bei einem Merge-Konflikt die als ours berichtete Seite die bisher rebasete Serie, beginnend mit <upstream>, und theirs ist der Arbeitsbranch. Mit anderen Worten, die Seiten sind vertauscht.

Siehe auch INKOMPATIBLE OPTIONEN unten.

-s <strategy>
--strategy=<strategy>

Verwenden Sie die angegebene Merge-Strategie anstelle der Standard-Strategie ort. Dies impliziert --merge.

Da git rebase jeden Commit vom Arbeitsbranch auf den <upstream>-Branch unter Verwendung der angegebenen Strategie wiederholt, leert die Verwendung der ours-Strategie einfach alle Patches aus dem <branch>, was wenig Sinn ergibt.

Siehe auch INKOMPATIBLE OPTIONEN unten.

-X <strategy-option>
--strategy-option=<strategy-option>

Leiten Sie die <strategy-option> an die Merge-Strategie weiter. Dies impliziert --merge und, falls keine Strategie angegeben wurde, -s ort. Beachten Sie die Vertauschung von ours und theirs, wie oben für die Option -m erläutert.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--rerere-autoupdate
--no-rerere-autoupdate

Nachdem der rerere-Mechanismus eine aufgezeichnete Auflösung für den aktuellen Konflikt wiederverwendet hat, um die Dateien im Arbeitsbaum zu aktualisieren, erlauben Sie ihm auch, den Index mit dem Ergebnis der Auflösung zu aktualisieren. --no-rerere-autoupdate ist eine gute Möglichkeit, zu überprüfen, was rerere getan hat, und potenzielle Fehlmerges zu erkennen, bevor das Ergebnis mit einem separaten git add in den Index übernommen wird.

-S[<keyid>]
--gpg-sign[=<keyid>]
--no-gpg-sign

GPG-sign Commits. Das Argument keyid ist optional und standardmäßig die Committer-Identität; wenn es angegeben wird, muss es ohne Leerzeichen an die Option angehängt werden. --no-gpg-sign ist nützlich, um sowohl die Konfigurationsvariable commit.gpgSign als auch einen früheren Befehl --gpg-sign zu überschreiben.

-q
--quiet

Seien Sie leise. Impliziert --no-stat.

-v
--verbose

Seien Sie ausführlich. Impliziert --stat.

--stat

Zeigen Sie einen Diffstat an, der zeigt, was sich seit dem letzten Rebase beim Upstream geändert hat. Der Diffstat wird auch durch die Konfigurationsoption rebase.stat gesteuert.

-n
--no-stat

Zeigen Sie keinen Diffstat als Teil des Rebase-Prozesses an.

--no-verify

Diese Option umgeht den Pre-Rebase-Hook. Siehe auch githooks[5].

--verify

Erlaubt das Ausführen des Pre-Rebase-Hooks, was die Standardeinstellung ist. Diese Option kann verwendet werden, um --no-verify zu überschreiben. Siehe auch githooks[5].

-C<n>

Stellen Sie sicher, dass mindestens <n> Zeilen umgebenden Kontext vor und nach jeder Änderung übereinstimmen. Wenn weniger Zeilen umgebenden Kontext vorhanden sind, müssen sie alle übereinstimmen. Standardmäßig wird nie Kontext ignoriert. Impliziert --apply.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--no-ff
--force-rebase
-f

Wenden Sie jeden neu basierenden Commit einzeln erneut an, anstatt unveränderte Commits per Fast-Forward zu überspringen. Dies stellt sicher, dass die gesamte Historie des neu basierenden Branches aus neuen Commits besteht.

Dies kann hilfreich sein, nachdem ein Merge eines Topic-Branches rückgängig gemacht wurde, da diese Option den Topic-Branch mit neuen Commits neu erstellt, damit er erfolgreich neu gemergt werden kann, ohne dass eine "Rückgängigmachung der Rückgängigmachung" erforderlich ist (siehe das How-To revert-a-faulty-merge für Details).

--fork-point
--no-fork-point

Verwenden Sie das Reflog, um einen besseren gemeinsamen Vorfahren zwischen <upstream> und <branch> zu finden, wenn Sie berechnen, welche Commits von <branch> eingeführt wurden.

Wenn --fork-point aktiv ist, wird fork_point anstelle von <upstream> verwendet, um die Menge der zu rebasenden Commits zu berechnen, wobei fork_point das Ergebnis des Befehls git merge-base --fork-point <upstream> <branch> ist (siehe git-merge-base[1]). Wenn fork_point leer ist, wird <upstream> als Fallback verwendet.

Wenn <upstream> oder --keep-base auf der Befehlszeile angegeben werden, ist die Standardeinstellung --no-fork-point, andernfalls ist die Standardeinstellung --fork-point. Siehe auch rebase.forkpoint in git-config[1].

Wenn Ihr Branch auf <upstream> basierte, aber <upstream> zurückgespult wurde und Ihr Branch Commits enthält, die verworfen wurden, kann diese Option mit --keep-base verwendet werden, um diese Commits aus Ihrem Branch zu entfernen.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--ignore-whitespace

Ignorieren Sie Whitespace-Unterschiede beim Versuch, Unterschiede abzugleichen. Derzeit implementiert jedes Backend eine Annäherung dieses Verhaltens.

apply backend

Beim Anwenden eines Patches ignorieren Sie Änderungen im Whitespace in Kontextzeilen. Unglücklicherweise bedeutet dies, dass, wenn die "alten" Zeilen, die durch den Patch ersetzt werden, sich nur im Whitespace vom bestehenden Dateiinhalt unterscheiden, Sie einen Merge-Konflikt anstelle einer erfolgreichen Patch-Anwendung erhalten.

merge backend

Behandeln Sie Zeilen mit reinen Whitespace-Änderungen als unverändert beim Mergen. Unglücklicherweise bedeutet dies, dass alle Patch-Hunks, die nur Whitespace ändern sollten und nichts anderes, verworfen werden, selbst wenn die andere Seite keine Änderungen hatte, die kollidierten.

--whitespace=<option>

Dieses Flag wird an das Programm git apply (siehe git-apply[1]) übergeben, das den Patch anwendet. Impliziert --apply.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--committer-date-is-author-date

Anstatt die aktuelle Zeit als Committer-Datum zu verwenden, verwenden Sie das Autor-Datum des neu basierenden Commits als Committer-Datum. Diese Option impliziert --force-rebase.

--ignore-date
--reset-author-date

Anstatt das Autor-Datum des ursprünglichen Commits zu verwenden, verwenden Sie die aktuelle Zeit als Autor-Datum des neu basierenden Commits. Diese Option impliziert --force-rebase.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--signoff

Fügen Sie einen Signed-off-by Trailer zu allen neu basierenden Commits hinzu. Beachten Sie, dass, wenn --interactive angegeben ist, nur Commits, die zum Aufnehmen, Bearbeiten oder Umformulieren markiert sind, den Trailer erhalten.

Siehe auch INKOMPATIBLE OPTIONEN unten.

-i
--interactive

Erstellen Sie eine Liste der Commits, die gerade rebased werden. Lassen Sie den Benutzer diese Liste bearbeiten, bevor Sie mit dem Rebase fortfahren. Dieser Modus kann auch zum Aufteilen von Commits verwendet werden (siehe COMMITS AUFTEILEN unten).

Das Format der Commit-Liste kann durch Setzen der Konfigurationsoption rebase.instructionFormat geändert werden. Ein angepasstes Instruktionsformat erhält automatisch den Commit-Hash am Anfang des Formats.

Siehe auch INKOMPATIBLE OPTIONEN unten.

-r
--rebase-merges[=(rebase-cousins|no-rebase-cousins)]
--no-rebase-merges

Standardmäßig wird bei einem Rebase einfach die Merge-Commits aus der Todo-Liste gelöscht und die neu basierenden Commits in einem einzigen, linearen Branch abgelegt. Mit --rebase-merges versucht der Rebase stattdessen, die Verzweigungsstruktur innerhalb der zu rebasenden Commits zu erhalten, indem die Merge-Commits neu erstellt werden. Alle aufgetretenen Merge-Konflikte oder manuellen Änderungen in diesen Merge-Commits müssen manuell behoben/wieder angewendet werden. --no-rebase-merges kann verwendet werden, um sowohl die Konfigurationsoption rebase.rebaseMerges als auch eine vorherige Option --rebase-merges zu überschreiben.

Beim Rebasen von Merges gibt es zwei Modi: rebase-cousins und no-rebase-cousins. Wenn der Modus nicht angegeben ist, ist die Standardeinstellung no-rebase-cousins. Im Modus no-rebase-cousins behalten Commits, die nicht <upstream> als direkten Vorfahren haben, ihren ursprünglichen Verzweigungspunkt, d.h. Commits, die von git log[1]'s Option --ancestry-path ausgeschlossen würden, behalten standardmäßig ihre ursprüngliche Abstammung. Im Modus rebase-cousins werden solche Commits stattdessen auf <upstream> (oder <onto>, falls angegeben) rebased.

Es ist derzeit nur möglich, die Merge-Commits mit der Merge-Strategie ort neu zu erstellen; verschiedene Merge-Strategien können nur über explizite Befehle exec git merge -s <strategy> [...] verwendet werden.

Siehe auch MERGES REBASEN und INKOMPATIBLE OPTIONEN unten.

-x <cmd>
--exec <cmd>

Hängen Sie "exec <cmd>" nach jeder Zeile an, die einen Commit in der endgültigen Historie erstellt. <cmd> wird als ein oder mehrere Shell-Befehle interpretiert. Jeder Befehl, der fehlschlägt, unterbricht den Rebase mit dem Exit-Code 1.

Sie können mehrere Befehle ausführen, entweder mit einer Instanz von --exec mit mehreren Befehlen:

git rebase -i --exec "cmd1 && cmd2 && ..."

oder durch Angabe von mehr als einem --exec:

git rebase -i --exec "cmd1" --exec "cmd2" --exec ...

Wenn --autosquash verwendet wird, werden exec-Zeilen nicht für die Zwischen-Commits angehängt und erscheinen nur am Ende jeder Squash/Fixup-Serie.

Dies verwendet die interne Maschinerie von --interactive, kann aber auch ohne explizites --interactive ausgeführt werden.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--root

Rebasen Sie alle Commits, die von <branch> erreichbar sind, anstatt sie mit einem <upstream> zu begrenzen. Dies ermöglicht es Ihnen, den Wurzel-Commit (die Wurzel-Commits) eines Branches zu rebasen.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--autosquash
--no-autosquash

Automatisch Commits mit speziell formatierten Nachrichten in vorherige Commits, die gerade rebased werden, einfügen. Wenn eine Commit-Nachricht mit "squash! ", "fixup! " oder "amend! " beginnt, wird der Rest des Titels als Commit-Spezifizierer verwendet, der mit einem vorherigen Commit übereinstimmt, wenn er dem Titel oder dem Hash dieses Commits entspricht. Wenn kein Commit vollständig übereinstimmt, werden Übereinstimmungen des Spezifizierers mit dem Anfang von Commit-Titeln berücksichtigt.

In der Rebase-Todo-Liste werden die Aktionen von Squash-, Fixup- und Amend-Commits von pick zu squash, fixup oder fixup -C geändert und sie werden direkt nach dem Commit verschoben, den sie modifizieren. Die Option --interactive kann verwendet werden, um die Todo-Liste vor dem Fortfahren zu überprüfen und zu bearbeiten.

Die empfohlene Methode zur Erstellung von Commits mit Squash-Markern ist die Verwendung der Optionen --squash, --fixup, --fixup=amend: oder --fixup=reword: von git-commit[1], die das Ziel-Commit als Argument nehmen und den Titel des neuen Commits automatisch daraus füllen.

Das Setzen der Konfigurationsvariable rebase.autoSquash auf true aktiviert Auto-Squash standardmäßig für interaktive Rebase. Die Option --no-autosquash kann verwendet werden, um diese Einstellung zu überschreiben.

Siehe auch INKOMPATIBLE OPTIONEN unten.

--autostash
--no-autostash

Erstellen Sie automatisch einen temporären Stash-Eintrag, bevor die Operation beginnt, und wenden Sie ihn nach Abschluss der Operation an. Das bedeutet, dass Sie Rebase auf einem schmutzigen Arbeitsbaum ausführen können. Verwenden Sie dies jedoch mit Vorsicht: die endgültige Stash-Anwendung nach einem erfolgreichen Rebase kann zu nicht-trivialen Konflikten führen.

--reschedule-failed-exec
--no-reschedule-failed-exec

Planen Sie exec-Befehle, die fehlgeschlagen sind, automatisch neu. Dies ist nur im interaktiven Modus sinnvoll (oder wenn eine --exec-Option angegeben wurde).

Diese Option wird angewendet, sobald ein Rebase gestartet wurde. Sie wird für den gesamten Rebase beibehalten, basierend auf, in Reihenfolge, der auf der Befehlszeile für den anfänglichen git rebase angegebenen Option, der Konfiguration rebase.rescheduleFailedExec (siehe git-config[1] oder "KONFIGURATION" unten), oder standardmäßig auf false gesetzt.

Das Aufzeichnen dieser Option für den gesamten Rebase ist eine Komfortfunktion. Andernfalls würde ein explizites --no-reschedule-failed-exec am Anfang durch die Anwesenheit einer Konfiguration rebase.rescheduleFailedExec=true überschrieben werden, wenn git rebase --continue aufgerufen wird. Derzeit können Sie --[no-]reschedule-failed-exec nicht an git rebase --continue übergeben.

--update-refs
--no-update-refs

Aktualisieren Sie automatisch alle Branches, die auf neu basierende Commits zeigen, mit einem Force-Update. Alle Branches, die in einem Worktree ausgecheckt sind, werden auf diese Weise nicht aktualisiert.

Wenn die Konfigurationsvariable rebase.updateRefs gesetzt ist, kann diese Option verwendet werden, um diese Einstellung zu überschreiben und zu deaktivieren.

Siehe auch INKOMPATIBLE OPTIONEN unten.

INKOMPATIBLE OPTIONEN

Die folgenden Optionen

  • --apply

  • --whitespace

  • -C

sind inkompatibel mit den folgenden Optionen

  • --merge

  • --strategy

  • --strategy-option

  • --autosquash

  • --rebase-merges

  • --interactive

  • --exec

  • --no-keep-empty

  • --empty=

  • --[no-]reapply-cherry-picks, wenn ohne --keep-base verwendet

  • --update-refs

  • --root, wenn ohne --onto verwendet

Zusätzlich sind die folgenden Optionenpaare inkompatibel:

  • --keep-base und --onto

  • --keep-base und --root

  • --fork-point und --root

VERHALTENSUNTERSCHIEDE

git rebase hat zwei Haupt-Backends: apply und merge. (Das apply-Backend war früher als am-Backend bekannt, aber der Name führte zu Verwirrung, da er wie ein Verb und nicht wie ein Nomen klingt. Auch das merge-Backend war früher als interaktives Backend bekannt, wird aber jetzt auch für nicht-interaktive Fälle verwendet. Beide wurden basierend auf den zugrunde liegenden Funktionalitäten, die jedem zugrunde liegen, umbenannt.) Es gibt einige subtile Unterschiede in der Funktionsweise dieser beiden Backends.

Leere Commits

Das apply-Backend verwirft leider absichtlich leere Commits, d.h. Commits, die ursprünglich leer waren, obwohl diese in der Praxis selten vorkommen. Es verwirft auch Commits, die leer werden, und es gibt keine Option, dieses Verhalten zu steuern.

Das merge-Backend behält absichtlich leere Commits standardmäßig bei (obwohl sie mit -i in der Todo-Listen-Editor als leer markiert werden oder automatisch mit --no-keep-empty verworfen werden können).

Ähnlich wie das apply-Backend verwirft das merge-Backend standardmäßig Commits, die leer werden, es sei denn, -i/--interactive wird angegeben (in diesem Fall stoppt es und fragt den Benutzer, was zu tun ist). Das merge-Backend hat auch eine Option --empty=(drop|keep|stop), um das Verhalten beim Umgang mit Commits, die leer werden, zu ändern.

Verzeichnissumbenennungserkennung

Aufgrund des Mangels an genauen Baum-Informationen (die sich aus der Erstellung gefälschter Vorfahren mit den begrenzten Informationen ergeben, die in Patches verfügbar sind), ist die Verzeichnissumbenennungserkennung im apply-Backend deaktiviert. Deaktivierte Verzeichnissumbenennungserkennung bedeutet, dass, wenn eine Seite der Historie ein Verzeichnis umbenennt und die andere neue Dateien in das alte Verzeichnis hinzufügt, die neuen Dateien im alten Verzeichnis zurückbleiben, ohne dass während des Rebasings eine Warnung ausgegeben wird, dass Sie diese Dateien möglicherweise in das neue Verzeichnis verschieben möchten.

Die Verzeichnissumbenennungserkennung funktioniert mit dem merge-Backend, um Sie in solchen Fällen zu warnen.

Kontext

Das apply-Backend erstellt eine Sequenz von Patches (durch internen Aufruf von format-patch) und wendet dann die Patches in Sequenz an (interner Aufruf von am). Patches bestehen aus mehreren "Hunks", die jeweils Zeilennummern, einen Kontextbereich und die eigentlichen Änderungen enthalten. Die Zeilennummern müssen mit einem gewissen Offset betrachtet werden, da die andere Seite wahrscheinlich früher in der Datei Zeilen eingefügt oder gelöscht hat. Der Kontextbereich dient dazu, die Zeilennummern anzupassen, um die Änderungen an den richtigen Zeilen anzuwenden. Wenn jedoch mehrere Bereiche des Codes die gleichen umliegenden Zeilen als Kontext haben, kann der falsche ausgewählt werden. Es gibt reale Fälle, in denen dies dazu geführt hat, dass Commits falsch neu angewendet wurden, ohne dass Konflikte gemeldet wurden. Das Setzen von diff.context auf einen größeren Wert kann solche Probleme verhindern, erhöht aber die Wahrscheinlichkeit von Scheinkonflikten (da mehr übereinstimmende Kontextzeilen zum Anwenden erforderlich sind).

Das merge-Backend arbeitet mit einer vollständigen Kopie jeder relevanten Datei und schützt es so vor diesen Arten von Problemen.

Beschriftung von Konfliktmarkern

Bei Inhaltskonflikten versucht die Merge-Maschinerie, die Konfliktmarker jeder Seite mit den Commits zu annotieren, aus denen der Inhalt stammt. Da das apply-Backend die ursprünglichen Informationen über die neu angewendeten Commits und ihre Eltern verwirft (und stattdessen neue gefälschte Commits basierend auf begrenzten Informationen in den generierten Patches erstellt), können diese Commits nicht identifiziert werden; stattdessen muss es auf eine Commit-Zusammenfassung zurückgreifen. Auch wenn merge.conflictStyle auf diff3 oder zdiff3 gesetzt ist, verwendet das apply-Backend eine "konstruierte Merge-Basis", um den Inhalt von der Merge-Basis zu beschriften, und liefert somit keine Informationen über den Merge-Basis-Commit.

Das merge-Backend arbeitet mit den vollständigen Commits auf beiden Seiten der Historie und hat daher keine solchen Einschränkungen.

Hooks

Das apply-Backend ruft traditionell nicht den Post-Commit-Hook auf, während das merge-Backend dies tut. Beide rufen den Post-Checkout-Hook auf, obwohl das merge-Backend seine Ausgabe unterdrückt. Darüber hinaus rufen beide Backends den Post-Checkout-Hook nur mit dem Start-Commit des Rebase auf, nicht mit den Zwischen-Commits oder dem End-Commit. In jedem Fall war das Aufrufen dieser Hooks ein Zufall der Implementierung und nicht des Designs (beide Backends wurden ursprünglich als Shell-Skripte implementiert und riefen zufällig andere Befehle wie git checkout oder git commit auf, die die Hooks aufrufen würden). Beide Backends sollten das gleiche Verhalten aufweisen, obwohl nicht ganz klar ist, welches, wenn überhaupt, korrekt ist. Wir werden wahrscheinlich dafür sorgen, dass rebase das Aufrufen dieser Hooks in Zukunft einstellt.

Unterbrechbarkeit

Das apply-Backend hat Sicherheitsprobleme bei einer ungünstig getimten Unterbrechung; wenn der Benutzer zur falschen Zeit Strg+C drückt, um den Rebase abzubrechen, kann der Rebase in einen Zustand geraten, in dem er mit einem nachfolgenden git rebase --abort nicht abgebrochen werden kann. Das merge-Backend scheint nicht unter demselben Mangel zu leiden. (Siehe https://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/ für Details.)

Commit-Umbenennung

Wenn während des Rebasings ein Konflikt auftritt, stoppt rebase und bittet den Benutzer, ihn zu lösen. Da der Benutzer möglicherweise bemerkenswerte Änderungen vornehmen muss, während er Konflikte löst, sollte der Rebase nach dem Lösen der Konflikte und dem Ausführen von git rebase --continue durch den Benutzer einen Editor öffnen und den Benutzer bitten, die Commit-Nachricht zu aktualisieren. Das merge-Backend tut dies, während das apply-Backend blind die ursprüngliche Commit-Nachricht anwendet.

Sonstige Unterschiede

Es gibt einige weitere Verhaltensunterschiede, die die meisten Leute wahrscheinlich für unerheblich halten würden, die aber der Vollständigkeit halber erwähnt werden.

  • Reflog: Die beiden Backends verwenden unterschiedliche Formulierungen, wenn sie die im Reflog vorgenommenen Änderungen beschreiben, obwohl beide das Wort "rebase" verwenden.

  • Fortschritts-, Informations- und Fehlermeldungen: Die beiden Backends liefern leicht unterschiedliche Fortschritts- und Informationsmeldungen. Außerdem schreibt das apply-Backend Fehlermeldungen (wie "Ihre Dateien würden überschrieben ...") nach stdout, während das merge-Backend sie nach stderr schreibt.

  • Statusverzeichnisse: Die beiden Backends speichern ihren Status in verschiedenen Verzeichnissen unter .git/.

MERGE-STRATEGIEN

Der Merge-Mechanismus (git merge und git pull Befehle) erlaubt die Auswahl der Backend-Merge-Strategien mit der Option -s. Einige Strategien können auch ihre eigenen Optionen haben, die durch Angabe von -X<option>-Argumenten an git merge und/oder git pull übergeben werden können.

ort

Dies ist die Standard-Merge-Strategie beim Ziehen oder Zusammenführen eines Branches. Diese Strategie kann nur zwei Heads mit einem 3-Wege-Merge-Algorithmus auflösen. Wenn es mehr als einen gemeinsamen Vorfahren gibt, der für einen 3-Wege-Merge verwendet werden kann, erstellt sie einen zusammengeführten Baum der gemeinsamen Vorfahren und verwendet diesen als Referenzbaum für den 3-Wege-Merge. Dies führt Berichten zufolge zu weniger Merge-Konflikten, ohne Fehlmerges zu verursachen, wie Tests mit tatsächlichen Merge-Commits aus der Linux 2.6 Kernel-Entwicklungshistorie zeigen. Zusätzlich kann diese Strategie das Erkennen und Behandeln von Merges mit Umbenennungen. Sie nutzt keine erkannten Kopien. Der Name für diesen Algorithmus ist ein Akronym ("Ostensibly Recursive’s Twin") und entstand aus der Tatsache, dass er als Ersatz für den vorherigen Standardalgorithmus, recursive, geschrieben wurde.

In Fällen, in denen der Pfad ein Submodul ist, wenn der auf einer Seite des Merges verwendete Submodul-Commit ein Nachfahre des auf der anderen Seite des Merges verwendeten Submodul-Commits ist, versucht Git, zum Nachfahren zu wechseln. Andernfalls behandelt Git diesen Fall als Konflikt und schlägt als Auflösung einen Submodul-Commit vor, der ein Nachfahre der konfligierenden ist, falls einer existiert.

Die ort-Strategie kann die folgenden Optionen annehmen

ours

Diese Option erzwingt die automatische Auflösung von konfligierenden Hunks, indem sie die Version von *unserer* Seite bevorzugt. Änderungen vom anderen Baum, die nicht mit unserer Seite kollidieren, werden im Merge-Ergebnis berücksichtigt. Bei einer Binärdatei werden die gesamten Inhalte von unserer Seite übernommen.

Dies sollte nicht mit der ours-Merge-Strategie verwechselt werden, die nicht einmal den anderen Baum betrachtet. Sie verwirft alles, was der andere Baum enthält, und erklärt, dass *unser* Verlauf alles enthält, was darin passiert ist.

theirs

Dies ist das Gegenteil von ours; beachte, dass es im Gegensatz zu ours keine theirs-Merge-Strategie gibt, mit der man diese Merge-Option verwechseln könnte.

ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol

Behandelt Zeilen mit der angegebenen Art von Leerzeichenänderung als unverändert für den Zweck eines Drei-Wege-Merges. Leerzeichenänderungen, die mit anderen Änderungen an einer Zeile vermischt sind, werden nicht ignoriert. Siehe auch git-diff[1] -b, -w, --ignore-space-at-eol und --ignore-cr-at-eol.

  • Wenn die *ihre* Version nur Leerzeichenänderungen an einer Zeile einführt, wird *unsere* Version verwendet;

  • Wenn *unsere* Version Leerzeichenänderungen einführt, aber *ihre* Version eine wesentliche Änderung enthält, wird *ihre* Version verwendet;

  • Andernfalls wird der Merge wie gewohnt fortgesetzt.

renormalize

Führt einen virtuellen Checkout und Check-in aller drei Stufen jeder Datei durch, die einen Drei-Wege-Merge benötigt. Diese Option ist für das Mergen von Branches mit unterschiedlichen Clean-Filtern oder End-of-Line-Normalisierungsregeln gedacht. Siehe "Merging branches with differing checkin/checkout attributes" in gitattributes[5] für Details.

no-renormalize

Deaktiviert die Option renormalize. Dies überschreibt die Konfigurationsvariable merge.renormalize.

find-renames[=<n>]

Schaltet die Erkennung von Umbenennungen ein und setzt optional den Ähnlichkeitsschwellenwert. Dies ist die Standardeinstellung. Dies überschreibt die Konfigurationsvariable merge.renames. Siehe auch git-diff[1] --find-renames.

rename-threshold=<n>

Veraltetes Synonym für find-renames=<n>.

no-renames

Schaltet die Erkennung von Umbenennungen aus. Dies überschreibt die Konfigurationsvariable merge.renames. Siehe auch git-diff[1] --no-renames.

histogram

Veraltetes Synonym für diff-algorithm=histogram.

patience

Veraltetes Synonym für diff-algorithm=patience.

diff-algorithm=(histogram|minimal|myers|patience)

Verwendet einen anderen Diff-Algorithmus beim Mergen, der helfen kann, Fehlmerges zu vermeiden, die aufgrund unwichtiger übereinstimmender Zeilen (wie Klammern aus unterschiedlichen Funktionen) auftreten. Siehe auch git-diff[1] --diff-algorithm. Beachten Sie, dass ort standardmäßig diff-algorithm=histogram verwendet, während normale Diffs derzeit standardmäßig auf die Konfigurationseinstellung diff.algorithm zurückgreifen.

subtree[=<path>]

Diese Option ist eine fortgeschrittenere Form der Subtree-Strategie, bei der die Strategie eine Vermutung darüber anstellt, wie zwei Bäume verschoben werden müssen, um zueinander zu passen, wenn sie gemerged werden. Stattdessen wird der angegebene Pfad vorangestellt (oder vom Anfang entfernt), um die Form zweier Bäume anzupassen.

recursive

Dies ist jetzt ein Synonym für ort. Es war bis v2.49.0 eine alternative Implementierung, wurde aber in v2.50.0 auf ort umgeleitet. Die frühere rekursive Strategie war die Standardstrategie zum Auflösen von zwei Heads von Git v0.99.9k bis v2.33.0.

resolve

Dies kann nur zwei Heads (d.h. den aktuellen Branch und einen anderen von Ihnen gezogenen Branch) mittels eines 3-Wege-Merge-Algorithmus auflösen. Es versucht, Kreuz-Merge-Mehrdeutigkeiten sorgfältig zu erkennen. Es behandelt keine Umbenennungen.

octopus

Dies löst Fälle mit mehr als zwei Heads auf, weigert sich aber, einen komplexen Merge durchzuführen, der eine manuelle Auflösung erfordert. Er ist hauptsächlich dazu gedacht, Topic-Branch-Heads zu bündeln. Dies ist die Standard-Merge-Strategie beim Ziehen oder Zusammenführen von mehr als einem Branch.

ours

Dies löst eine beliebige Anzahl von Heads auf, aber der resultierende Baum des Merges ist immer der des aktuellen Branch-Heads, wobei alle Änderungen von allen anderen Branches effektiv ignoriert werden. Er ist dazu gedacht, die alte Entwicklungsgeschichte von Seiten-Branches zu ersetzen. Beachten Sie, dass dies sich von der Option -Xours zur ort-Merge-Strategie unterscheidet.

subtree

Dies ist eine modifizierte ort-Strategie. Beim Mergen der Bäume A und B wird, wenn B einem Subtree von A entspricht, B zuerst angepasst, um die Baumstruktur von A abzugleichen, anstatt die Bäume auf derselben Ebene zu lesen. Diese Anpassung wird auch auf den gemeinsamen Vorfahren-Baum angewendet.

Mit den Strategien, die 3-Wege-Merges verwenden (einschließlich der Standardstrategie ort), wird eine Änderung, die auf beiden Branches vorgenommen wurde, aber später auf einem der Branches rückgängig gemacht wurde, im zusammengeführten Ergebnis vorhanden sein; einige Leute finden dieses Verhalten verwirrend. Es tritt auf, weil nur die Heads und die Merge-Basis für die Durchführung eines Merges berücksichtigt werden, nicht die einzelnen Commits. Der Merge-Algorithmus betrachtet daher die rückgängig gemachte Änderung als keine Änderung und ersetzt sie stattdessen durch die geänderte Version.

HINWEISE

Sie sollten die Auswirkungen der Verwendung von git rebase auf ein gemeinsam genutztes Repository verstehen. Siehe auch RECOVERING FROM UPSTREAM REBASE unten.

Wenn der Rebase ausgeführt wird, wird zuerst ein pre-rebase Hook aufgerufen, falls vorhanden. Sie können diesen Hook verwenden, um Integritätsprüfungen durchzuführen und den Rebase abzulehnen, wenn er nicht angemessen ist. Bitte beachten Sie das Vorlagen-Skript pre-rebase für ein Beispiel.

Nach Abschluss ist <branch> der aktuelle Branch.

INTERAKTIVER MODUS

Interaktives Rebasen bedeutet, dass Sie die Möglichkeit haben, die neu angewendeten Commits zu bearbeiten. Sie können die Commits neu anordnen und entfernen (schlechte oder anderweitig unerwünschte Patches aussondern).

Der interaktive Modus ist für diesen Workflow gedacht

  1. eine wunderbare Idee haben

  2. am Code hacken

  3. eine Serie zur Einreichung vorbereiten

  4. einreichen

wobei Punkt 2. mehrere Instanzen von

a) reguläre Nutzung

  1. etwas fertigstellen, das einen Commit wert ist

  2. commit

b) unabhängige Korrektur

  1. merken, dass etwas nicht funktioniert

  2. das beheben

  3. commit

Manchmal kann das in b.2. behobene Problem nicht an den nicht ganz perfekten Commit angehängt werden, den es behebt, weil dieser Commit tief in einer Patch-Serie vergraben ist. Genau dafür ist das interaktive Rebase gedacht: Verwenden Sie es nach vielen "a"s und "b"s, indem Sie Commits neu anordnen und bearbeiten und mehrere Commits zu einem zusammenfassen.

Starten Sie es mit dem letzten Commit, den Sie unverändert beibehalten möchten.

git rebase -i <after-this-commit>

Ein Editor wird mit allen Commits in Ihrem aktuellen Branch (unter Ignorierung von Merge-Commits) gestartet, die nach dem angegebenen Commit kommen. Sie können die Commits in dieser Liste nach Belieben neu anordnen und entfernen. Die Liste sieht mehr oder weniger so aus

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Die Einzeiler-Beschreibungen dienen nur Ihrer Freude; git rebase wird sie nicht ansehen, sondern die Commit-Namen ("deadbee" und "fa1afe1" in diesem Beispiel), also löschen oder bearbeiten Sie die Namen nicht.

Durch Ersetzen des Befehls "pick" durch den Befehl "edit" können Sie git rebase anweisen, nach dem Anwenden dieses Commits zu stoppen, damit Sie die Dateien und/oder die Commit-Nachricht bearbeiten, den Commit ändern und mit dem Rebasen fortfahren können.

Um den Rebase zu unterbrechen (genau wie bei einem "edit"-Befehl, aber ohne vorherige Übernahme eines Commits), verwenden Sie den Befehl "break".

Wenn Sie nur die Commit-Nachricht eines Commits bearbeiten möchten, ersetzen Sie den Befehl "pick" durch den Befehl "reword".

Um einen Commit zu verwerfen, ersetzen Sie den Befehl "pick" durch "drop" oder löschen Sie einfach die entsprechende Zeile.

Wenn Sie zwei oder mehr Commits zu einem zusammenführen möchten, ersetzen Sie den Befehl "pick" für den zweiten und nachfolgenden Commits durch "squash" oder "fixup". Wenn die Commits unterschiedliche Autoren hatten, wird der zusammengeführte Commit dem Autor des ersten Commits zugeschrieben. Die vorgeschlagene Commit-Nachricht für den zusammengeführten Commit ist die Verkettung der Nachricht des ersten Commits mit denen, die durch "squash"-Befehle identifiziert wurden, wobei die Nachrichten von durch "fixup"-Befehle identifizierten Commits weggelassen werden, es sei denn, "fixup -c" wird verwendet. In diesem Fall ist die vorgeschlagene Commit-Nachricht nur die Nachricht des "fixup -c"-Commits, und ein Editor wird geöffnet, der es Ihnen ermöglicht, die Nachricht zu bearbeiten. Der Inhalt (Patch) des "fixup -c"-Commits wird dennoch in den zusammengeführten Commit einbezogen. Wenn es mehr als einen "fixup -c"-Commit gibt, wird die Nachricht des letzten verwendet. Sie können auch "fixup -C" verwenden, um das gleiche Verhalten wie bei "fixup -c" zu erhalten, außer dass kein Editor geöffnet wird.

git rebase stoppt, wenn "pick" durch "edit" ersetzt wurde oder wenn ein Befehl aufgrund von Merge-Fehlern fehlschlägt. Wenn Sie mit der Bearbeitung und/oder dem Lösen von Konflikten fertig sind, können Sie mit git rebase --continue fortfahren.

Wenn Sie beispielsweise die letzten 5 Commits neu anordnen möchten, so dass HEAD~4 zum neuen HEAD wird. Um dies zu erreichen, würden Sie git rebase wie folgt aufrufen

$ git rebase -i HEAD~5

und den ersten Patch ans Ende der Liste verschieben.

Möglicherweise möchten Sie Merge-Commits neu erstellen, z. B. wenn Sie eine Historie wie diese haben

           X
            \
         A---M---B
        /
---o---O---P---Q

Angenommen, Sie möchten den Seiten-Branch, der bei "A" beginnt, auf "Q" rebasen. Stellen Sie sicher, dass der aktuelle HEAD "B" ist, und rufen Sie auf

$ git rebase -i -r --onto Q O

Das Neuordnen und Bearbeiten von Commits erzeugt normalerweise ungetestete Zwischenschritte. Möglicherweise möchten Sie überprüfen, ob Ihre Historienbearbeitung nichts kaputt gemacht hat, indem Sie einen Test durchführen oder zumindest an Zwischenpunkten der Historie neu kompilieren, indem Sie den Befehl "exec" (Abkürzung "x") verwenden. Dies können Sie tun, indem Sie eine Todo-Liste wie diese erstellen

pick deadbee Implement feature XXX
fixup f1a5c00 Fix to feature XXX
exec make
pick c0ffeee The oneline of the next commit
edit deadbab The oneline of the commit after
exec cd subdir; make test
...

Das interaktive Rebase stoppt, wenn ein Befehl fehlschlägt (d. h. mit einem Nicht-0-Status beendet wird), um Ihnen die Möglichkeit zu geben, das Problem zu beheben. Sie können mit git rebase --continue fortfahren.

Der Befehl "exec" startet den Befehl in einer Shell (der Standard-Shell, normalerweise /bin/sh), sodass Sie Shell-Funktionen (wie "cd", ">", ";" …) verwenden können. Der Befehl wird vom Stamm des Arbeitsbaums aus ausgeführt.

$ git rebase -i --exec "make test"

Dieser Befehl ermöglicht es Ihnen zu überprüfen, ob Zwischen-Commits kompilierbar sind. Die Todo-Liste wird dann so aussehen

pick 5928aea one
exec make test
pick 04d0fda two
exec make test
pick ba46169 three
exec make test
pick f4593f9 four
exec make test

COMMITS AUFTEILEN

Im interaktiven Modus können Sie Commits mit der Aktion "edit" markieren. Dies bedeutet jedoch nicht unbedingt, dass git rebase erwartet, dass das Ergebnis dieser Bearbeitung genau ein Commit ist. Tatsächlich können Sie den Commit rückgängig machen oder andere Commits hinzufügen. Dies kann verwendet werden, um einen Commit in zwei aufzuteilen.

  • Starten Sie einen interaktiven Rebase mit git rebase -i <commit>^, wobei <commit> der Commit ist, den Sie aufteilen möchten. Tatsächlich kann jeder Commit-Bereich ausreichen, solange er diesen Commit enthält.

  • Markieren Sie den zu teilenden Commit mit der Aktion "edit".

  • Wenn es an der Zeit ist, diesen Commit zu bearbeiten, führen Sie git reset HEAD^ aus. Dies bewirkt, dass HEAD um eins zurückgesetzt wird und der Index diesem folgt. Der Arbeitsbaum bleibt jedoch unverändert.

  • Fügen Sie nun die Änderungen zum Index hinzu, die Sie im ersten Commit haben möchten. Sie können dazu git add (ggf. interaktiv) oder git gui (oder beides) verwenden.

  • Comitten Sie den nun aktuellen Index mit der entsprechenden Commit-Nachricht.

  • Wiederholen Sie die letzten beiden Schritte, bis Ihr Arbeitsbaum sauber ist.

  • Fahren Sie mit dem Rebase mit git rebase --continue fort.

Wenn Sie sich nicht absolut sicher sind, dass die Zwischenrevisionen konsistent sind (sie kompilieren, bestehen den Test-Suite usw.), sollten Sie git stash verwenden, um die noch nicht committeten Änderungen nach jedem Commit wegzulegen, zu testen und den Commit zu ändern, wenn Korrekturen notwendig sind.

WIEDERHERSTELLUNG NACH UPSTREAM-REBASE

Das Rebasen (oder jede andere Form des Umschreibens) eines Branches, auf dem andere Arbeit aufgebaut haben, ist eine schlechte Idee: jeder nachfolgende Benutzer muss seine Historie manuell korrigieren. Dieser Abschnitt erklärt, wie die Korrektur aus der Sicht des nachfolgenden Benutzers vorgenommen wird. Die eigentliche Korrektur wäre jedoch, das Rebasen des Upstreams von vornherein zu vermeiden.

Zur Veranschaulichung nehmen wir an, Sie befinden sich in einer Situation, in der jemand einen Subsystem-Branch entwickelt und Sie an einem Thema arbeiten, das von diesem Subsystem abhängt. Möglicherweise haben Sie eine Historie wie die folgende

    o---o---o---o---o---o---o---o  master
	 \
	  o---o---o---o---o  subsystem
			   \
			    *---*---*  topic

Wenn subsystem gegen master neu angewendet wird, geschieht Folgendes

    o---o---o---o---o---o---o---o  master
	 \			 \
	  o---o---o---o---o	  o'--o'--o'--o'--o'  subsystem
			   \
			    *---*---*  topic

Wenn Sie nun die Entwicklung wie gewohnt fortsetzen und schließlich topic in subsystem mergen, bleiben die Commits von subsystem für immer dupliziert.

    o---o---o---o---o---o---o---o  master
	 \			 \
	  o---o---o---o---o	  o'--o'--o'--o'--o'--M	 subsystem
			   \			     /
			    *---*---*-..........-*--*  topic

Solche Duplikate werden im Allgemeinen missbilligt, da sie die Historie unübersichtlich machen und das Nachvollziehen erschweren. Um aufzuräumen, müssen Sie die Commits auf topic auf die neue subsystem-Spitze übertragen, d. h. topic neu anwenden. Dies wird zu einem Welleneffekt: Jeder nachfolgende Benutzer von topic muss ebenfalls neu anwenden und so weiter!

Es gibt zwei Arten von Korrekturen, die in den folgenden Unterabschnitten behandelt werden.

Einfacher Fall: Die Änderungen sind buchstäblich dieselben.

Dies geschieht, wenn das subsystem-Rebase ein einfaches Rebase war und keine Konflikte aufwies.

Schwerer Fall: Die Änderungen sind nicht dieselben.

Dies geschieht, wenn das subsystem-Rebase Konflikte hatte oder --interactive verwendete, um Commits wegzulassen, zu bearbeiten, zusammenzufassen oder zu korrigieren; oder wenn der Upstream einen der Befehle commit --amend, reset oder einen vollständigen Historien-Umschreibungsbefehl wie filter-repo verwendete.

Der einfache Fall

Funktioniert nur, wenn die Änderungen (Patch-IDs basierend auf den Diff-Inhalten) in subsystem vor und nach dem Rebase des subsystem buchstäblich gleich sind.

In diesem Fall ist die Korrektur einfach, weil git rebase weiß, dass bereits vorhandene Änderungen im neuen Upstream übersprungen werden (es sei denn, --reapply-cherry-picks wird angegeben). Wenn Sie also sagen (vorausgesetzt, Sie befinden sich auf topic)

    $ git rebase subsystem

erhalten Sie die korrigierte Historie.

    o---o---o---o---o---o---o---o  master
				 \
				  o'--o'--o'--o'--o'  subsystem
						   \
						    *---*---*  topic

Der schwere Fall

Die Dinge werden komplizierter, wenn die subsystem-Änderungen nicht exakt mit denen vor dem Rebase übereinstimmen.

Hinweis
Während eine "einfache Fall-Wiederherstellung" im schweren Fall manchmal erfolgreich zu sein scheint, kann sie unbeabsichtigte Folgen haben. Zum Beispiel wird ein Commit, der über git rebase --interactive entfernt wurde, **wiederbelebt**!

Die Idee ist, git rebase manuell mitzuteilen, "wo das alte subsystem endete und Ihr topic begann", d.h. was die alte gemeinsame Basis zwischen ihnen war. Sie müssen einen Weg finden, die letzte Commit des alten subsystem zu benennen, zum Beispiel

  • Mit dem Reflog von subsystem: Nach git fetch befindet sich die alte Spitze von subsystem bei subsystem@{1}. Nachfolgende Fetches erhöhen die Zahl. (Siehe git-reflog[1].)

  • Relativ zur Spitze von topic: Wenn Sie wissen, dass Ihr topic drei Commits hat, muss die alte Spitze von subsystem topic~3 sein.

Sie können dann die alten subsystem..topic-Commits auf die neue Spitze übertragen, indem Sie sagen (für den Reflog-Fall, und vorausgesetzt, Sie sind bereits auf topic)

    $ git rebase --onto subsystem subsystem@{1}

Der Welleneffekt einer "schweren Fall"-Wiederherstellung ist besonders schlimm: jeder nachfolgende Benutzer von topic muss ebenfalls eine "schwere Fall"-Wiederherstellung durchführen!

MERGES NEU ANWENDEN

Der interaktive Rebase-Befehl wurde ursprünglich für die Bearbeitung einzelner Patch-Serien entwickelt. Daher ist es sinnvoll, Merge-Commits aus der Todo-Liste auszuschließen, da der Entwickler möglicherweise den damaligen master gemerged hat, während er am Branch arbeitete, nur um später alle Commits auf master neu anzuwenden (und die Merge-Commits zu überspringen).

Es gibt jedoch legitime Gründe, warum ein Entwickler Merge-Commits neu erstellen möchte: um die Branch-Struktur (oder "Commit-Topologie") beizubehalten, wenn an mehreren, miteinander verbundenen Branches gearbeitet wird.

Im folgenden Beispiel arbeitet der Entwickler an einem Topic-Branch, der die Definition von Buttons refaktoriert, und an einem anderen Topic-Branch, der diese Refaktorisierung verwendet, um einen "Report a bug"-Button zu implementieren. Die Ausgabe von git log --graph --format=%s -5 könnte wie folgt aussehen

*   Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one

Der Entwickler möchte diese Commits möglicherweise auf einen neueren master neu anwenden, während die Branch-Topologie beibehalten wird, zum Beispiel, wenn erwartet wird, dass der erste Topic-Branch viel früher als der zweite in master integriert wird, um Merge-Konflikte mit Änderungen an der Klasse DownloadButton zu lösen, die es in master geschafft haben.

Dieser Rebase kann mit der Option --rebase-merges durchgeführt werden. Er generiert eine Todo-Liste, die wie folgt aussieht

label onto

# Branch: refactor-button
reset onto
pick 123456 Extract a generic Button class from the DownloadButton one
pick 654321 Use the Button class for all buttons
label refactor-button

# Branch: report-a-bug
reset refactor-button # Use the Button class for all buttons
pick abcdef Add the feedback button
label report-a-bug

reset onto
merge -C a1b2c3 refactor-button # Merge 'refactor-button'
merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'

Im Gegensatz zu einem regulären interaktiven Rebase gibt es neben den pick-Befehlen auch label-, reset- und merge-Befehle.

Der Befehl label ordnet der aktuellen HEAD ein Label zu, wenn dieser Befehl ausgeführt wird. Diese Labels werden als Worktree-lokale Refs (refs/rewritten/<label>) erstellt, die gelöscht werden, wenn der Rebase abgeschlossen ist. Auf diese Weise stören sich Rebase-Operationen in mehreren Worktrees, die mit demselben Repository verknüpft sind, nicht gegenseitig. Wenn der Befehl label fehlschlägt, wird er sofort neu geplant, mit einer hilfreichen Nachricht, wie fortzufahren ist.

Der Befehl reset setzt die HEAD, den Index und den Arbeitsbaum auf die angegebene Revision zurück. Er ist ähnlich wie ein exec git reset --hard <label>, weigert sich jedoch, nicht verfolgte Dateien zu überschreiben. Wenn der Befehl reset fehlschlägt, wird er sofort neu geplant, mit einer hilfreichen Nachricht, wie die Todo-Liste zu bearbeiten ist (dies geschieht typischerweise, wenn ein reset-Befehl manuell in die Todo-Liste eingefügt wurde und einen Tippfehler enthält).

Der Befehl merge wird die angegebene(n) Revision(en) mit dem jeweiligen HEAD mergen. Mit -C <original-commit> wird die Commit-Nachricht des angegebenen Merge-Commits verwendet. Wenn -C zu einem Kleinbuchstaben -c geändert wird, wird die Nachricht nach einem erfolgreichen Merge in einem Editor geöffnet, damit der Benutzer die Nachricht bearbeiten kann.

Wenn ein merge-Befehl aus anderen Gründen als Merge-Konflikten fehlschlägt (d. h. wenn die Merge-Operation nicht einmal begonnen hat), wird er sofort neu geplant.

Standardmäßig verwendet der Befehl merge die Merge-Strategie ort für reguläre Merges und octopus für Octopus-Merges. Man kann eine Standardstrategie für alle Merges über das Argument --strategy beim Aufrufen von rebase angeben, oder man kann spezifische Merges in der interaktiven Liste von Befehlen überschreiben, indem man einen exec-Befehl aufruft, um explizit git merge mit einem --strategy-Argument aufzurufen. Beachten Sie, dass Sie bei explizitem Aufruf von git merge die Tatsache nutzen können, dass die Labels Worktree-lokale Refs sind (die Ref refs/rewritten/onto würde beispielsweise dem Label onto entsprechen), um die zu mergenden Branches zu referenzieren.

Hinweis: Der erste Befehl (label onto) beschriftet die Revision, auf die die Commits neu angewendet werden; Der Name onto ist nur eine Konvention, als Anspielung auf die Option --onto.

Es ist auch möglich, völlig neue Merge-Commits von Grund auf neu zu erstellen, indem man einen Befehl der Form merge <merge-head> hinzufügt. Diese Form generiert eine vorläufige Commit-Nachricht und öffnet immer einen Editor, damit der Benutzer sie bearbeiten kann. Dies kann nützlich sein, z. B. wenn sich herausstellt, dass ein Topic-Branch mehr als ein einzelnes Anliegen betrifft und in zwei oder sogar mehr Topic-Branches aufgeteilt werden soll. Betrachten Sie diese Todo-Liste

pick 192837 Switch from GNU Makefiles to CMake
pick 5a6c7e Document the switch to CMake
pick 918273 Fix detection of OpenSSL in CMake
pick afbecd http: add support for TLS v1.3
pick fdbaec Fix detection of cURL in CMake on Windows

Der eine Commit in dieser Liste, der nicht mit CMake zusammenhängt, wurde möglicherweise durch die Behebung all der Fehler motiviert, die durch die Umstellung auf CMake eingeführt wurden, befasst sich aber mit einem anderen Anliegen. Um diesen Branch in zwei Topic-Branches aufzuteilen, könnte die Todo-Liste wie folgt bearbeitet werden

label onto

pick afbecd http: add support for TLS v1.3
label tlsv1.3

reset onto
pick 192837 Switch from GNU Makefiles to CMake
pick 918273 Fix detection of OpenSSL in CMake
pick fdbaec Fix detection of cURL in CMake on Windows
pick 5a6c7e Document the switch to CMake
label cmake

reset onto
merge tlsv1.3
merge cmake

KONFIGURATION

Alles unterhalb dieser Zeile in diesem Abschnitt wird selektiv aus der git-config[1]-Dokumentation übernommen. Der Inhalt ist derselbe wie dort zu finden.

rebase.backend

Standard-Backend, das für das Rebasen verwendet werden soll. Mögliche Optionen sind apply oder merge. In Zukunft, wenn das merge-Backend alle verbleibenden Fähigkeiten des apply-Backends erhält, wird diese Einstellung möglicherweise nicht mehr verwendet.

rebase.stat

Ob eine Diff-Statistik dessen angezeigt werden soll, was sich seit dem letzten Rebase upstream geändert hat. Standardmäßig False.

rebase.autoSquash

Wenn auf true gesetzt, wird die Option --autosquash von git-rebase[1] für den interaktiven Modus standardmäßig aktiviert. Dies kann mit der Option --no-autosquash überschrieben werden.

rebase.autoStash

Wenn auf true gesetzt, wird vor dem Beginn der Operation automatisch ein temporärer Stash-Eintrag erstellt und nach Beendigung der Operation wieder angewendet. Das bedeutet, dass Sie rebase auf einem "dirty" Working Tree ausführen können. Verwenden Sie dies jedoch mit Vorsicht: Das endgültige Anwenden des Stash nach einem erfolgreichen Rebase kann zu nicht trivialen Konflikten führen. Diese Option kann durch die Optionen --no-autostash und --autostash von git-rebase[1] überschrieben werden. Standardmäßig false.

rebase.updateRefs

Wenn auf true gesetzt, wird die Option --update-refs standardmäßig aktiviert.

rebase.missingCommitsCheck

Wenn auf "warn" gesetzt, wird git rebase -i eine Warnung ausgeben, wenn einige Commits entfernt werden (z.B. wenn eine Zeile gelöscht wurde), der Rebase wird jedoch fortgesetzt. Wenn auf "error" gesetzt, wird die vorherige Warnung ausgegeben und der Rebase gestoppt. git rebase --edit-todo kann dann verwendet werden, um den Fehler zu korrigieren. Wenn auf "ignore" gesetzt, wird keine Prüfung durchgeführt. Um einen Commit ohne Warnung oder Fehler zu verwerfen, verwenden Sie den Befehl drop in der To-do-Liste. Standardmäßig "ignore".

rebase.instructionFormat

Ein Formatstring, wie in git-log[1] spezifiziert, der für die To-do-Liste während eines interaktiven Rebase verwendet wird. Das Format wird automatisch mit dem Commit-Hash vorangestellt.

rebase.abbreviateCommands

Wenn auf true gesetzt, verwendet git rebase abgekürzte Befehlsnamen in der To-do-Liste, was zu etwas wie folgt führt:

	p deadbee The oneline of the commit
	p fa1afe1 The oneline of the next commit
	...

anstatt

	pick deadbee The oneline of the commit
	pick fa1afe1 The oneline of the next commit
	...

Standardmäßig false.

rebase.rescheduleFailedExec

Automatisch fehlgeschlagene exec-Befehle neu planen. Dies ist nur im interaktiven Modus sinnvoll (oder wenn eine Option --exec angegeben wurde). Dies entspricht der Angabe der Option --reschedule-failed-exec.

rebase.forkPoint

Wenn auf false gesetzt, wird die Option --no-fork-point standardmäßig gesetzt.

rebase.rebaseMerges

Ob und wie die Option --rebase-merges standardmäßig gesetzt wird. Kann rebase-cousins, no-rebase-cousins oder ein boolescher Wert sein. Das Setzen auf true oder no-rebase-cousins entspricht --rebase-merges=no-rebase-cousins, das Setzen auf rebase-cousins entspricht --rebase-merges=rebase-cousins und das Setzen auf false entspricht --no-rebase-merges. Das Übergeben von --rebase-merges auf der Kommandozeile, mit oder ohne Argument, überschreibt jede rebase.rebaseMerges Konfiguration.

rebase.maxLabelLength

Beim Generieren von Label-Namen aus Commit-Betreffzeilen werden die Namen auf diese Länge gekürzt. Standardmäßig werden die Namen auf etwas weniger als NAME_MAX gekürzt (um z.B. das Schreiben von .lock-Dateien für die entsprechenden lose Referenzen zu ermöglichen).

sequence.editor

Texteditor, der von git rebase -i zum Bearbeiten der Rebase-Instruktionsdatei verwendet wird. Der Wert ist für die Interpretation durch die Shell vorgesehen, wenn er verwendet wird. Er kann durch die Umgebungsvariable GIT_SEQUENCE_EDITOR überschrieben werden. Wenn nicht konfiguriert, wird stattdessen der Standard-Commit-Nachrichteneditor verwendet.

GIT

Teil der git[1] Suite