git rebase
Bedeutung des git rebase-Befehls, Verwendungsbeispiele und der Unterschied zwischen Standard- und interaktivem Git Rebase.
Was git rebase bewirkt
Rebasing bedeutet, eine Reihe von Commits auf einen neuen Basis-Commit zu verschieben. Mit anderen Worten: git rebase ändert den Startpunkt des aktuellen Branches von einem Commit zu einem anderen, sodass es aussieht, als hätte man den Branch von einem anderen Punkt in der Geschichte erstellt.
Das Wichtigste dabei: Rebase verschiebt nicht die ursprünglichen Commits. Es erstellt brandneue Commits mit denselben Änderungen und Commit-Nachrichten, aber anderen Eltern-Commits und damit anderen Commit-Hashes (SHAs). Die alten Commits werden unerreichbar, obwohl der Branch gleich aussieht.

Diese Seite behandelt den Standard-Rebase, den interaktiven Rebase, die --onto-Form, die Konfliktauflösung und die Wiederherstellung bei einem fehlgeschlagenen Rebase.
Rebase vs. Merge
Sowohl git rebase als auch git merge integrieren Änderungen von einem Branch in einen anderen, gestalten die Geschichte jedoch unterschiedlich:
- Merge erstellt einen neuen Merge-Commit, der die beiden Branch-Historien miteinander verbindet. Die Geschichte ist nicht-linear, aber vollständig erhalten — nichts wird umgeschrieben.
- Rebase spielt Ihre Commits auf dem Zielbranch neu ab. Die Geschichte bleibt linear (keine Merge-Commits), aber die ursprünglichen Commits werden umgeschrieben.
Verwenden Sie Rebase, wenn Sie eine saubere, geradlinige Historie für einen Feature-Branch vor dem Teilen wünschen. Verwenden Sie Merge, wenn Sie die genaue Geschichte erhalten möchten, wie Branches zusammengeführt wurden, oder wenn der Branch bereits öffentlich ist.
Standard-Rebase
Im Standardmodus nimmt git rebase die Commits, die nur in Ihrem aktuellen Branch vorhanden sind, und spielt sie auf <base> neu ab. Die <base> kann ein Branch-Name, ein Tag oder eine Commit-ID sein.
git rebase <base>Der typische Workflow: master hat sich weiterentwickelt, seit Sie davon abgezweigt haben, und Sie möchten die neuesten master-Änderungen unter Ihrer Feature-Arbeit haben, ohne einen Merge-Commit.
# you are on your feature branch
git switch feature
# replay feature's commits on top of the current tip of master
git rebase masterVor dem Rebase sieht die Historie so aus (Feature wurde von einem älteren master abgezweigt):
A---B---C feature
/
D---E---F---G masterNach git rebase master werden die Feature-Commits auf G neu erstellt:
A'--B'--C' feature
/
D---E---F---G masterA', B' und C' tragen dieselben Änderungen wie A, B, C, aber es sind neue Commits mit neuen Hashes.
Öffentliche Historie niemals rebasen
Rebasen Sie niemals Commits, die bereits gepusht wurden und auf denen andere Personen ihre Arbeit aufgebaut haben könnten. Da Rebase Commits durch neue ersetzt, werden alle, die die alten Commits gepullt haben, feststellen, dass ihre Historie nicht mehr synchron ist — es sieht so aus, als wäre ein Teil des Projekts verschwunden, und sie erhalten beim nächsten Pull doppelte oder konfliktreiche Commits.
Die goldene Regel des Rebasings: Rebasen Sie nur Commits, die ausschließlich auf Ihrem lokalen Branch existieren und noch nicht geteilt wurden. Das Rebasen bereits veröffentlichter Commits ist der häufigste Weg, wie Teams die Repositories der anderen beschädigen.
Die sichere Grenze ist einfach: Private Arbeit können Sie frei rebasen; rebasen Sie niemals den gemeinsamen master/main-Branch oder einen Branch, auf dem andere aktiv arbeiten. Dies ist dieselbe Vorsicht, die für git reset und git commit --amend gilt.
Interaktiver Rebase
Der interaktive Modus (-i, kurz für „interactive") ermöglicht es Ihnen, einzelne Commits beim Neuabspielen zu bearbeiten, umzuordnen, zusammenzuführen oder zu entfernen. Dies ist das Werkzeug, das Entwickler verwenden, um einen Feature-Branch vor dem Mergen zu bereinigen — kleine „Tippfehler korrigiert"-Commits zusammenzuführen, unklare Nachrichten umzuformulieren und Sackgassen-Experimente zu entfernen.
git rebase -i <base>Beispielsweise, um die letzten 3 Commits auf Ihrem Branch aufzuräumen:
git rebase -i HEAD~3Dadurch wird Ihr Editor mit einer „Todo"-Liste geöffnet — eine Zeile pro Commit, älteste oben:
pick 11a1456 Add login form
pick a23db19 Fix typo in label
pick 31d332c Add password validation
# Rebase d4e5f6a..31d332c onto d4e5f6a (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commitUm die Tippfehlerkorrektur in den Login-Form-Commit zusammenzuführen und den Validierungs-Commit umzubenennen, würden Sie die Liste wie folgt ändern:
pick 11a1456 Add login form
fixup a23db19 Fix typo in label
reword 31d332c Add password validationSpeichern und schließen Sie den Editor; Git spielt die Commits neu ab und wendet dabei jede Anweisung der Reihe nach an.
Befehle für den interaktiven Rebase
Jede Zeile in der Todo-Liste beginnt mit einem dieser Befehle:
pick— den Commit unverändert behalten. Dies ist der Standard für jede Zeile.reword— die Änderungen des Commits behalten, aber anhalten, um die Nachricht zu bearbeiten.edit— bei diesem Commit anhalten, damit Sie seinen Inhalt ändern können (aufteilen, Dateien hinzufügen usw.), danngit rebase --continue.squash— diesen Commit mit dem vorherigen zusammenführen und beide Nachrichten in eine kombinieren.fixup— wiesquash, aber die Nachricht dieses Commits verwerfen (nur die vorherige behalten).drop— den Commit vollständig aus der Historie entfernen.exec— nach dem vorherigen Commit einen Shell-Befehl ausführen (nützlich, um Tests bei jedem Schritt auszuführen).
Das Umsortieren der Zeilen ändert die Reihenfolge der Commits; das Löschen einer Zeile entspricht drop.
Die --onto-Form
Das --onto-Flag gibt Ihnen präzise Kontrolle darüber, welche Commits verschoben werden und wo sie landen:
git rebase --onto <newbase> <oldbase> <branch>Es nimmt die Commits, die in <branch>, aber nicht in <oldbase> vorhanden sind, und spielt sie auf <newbase> neu ab. So lässt sich ein Branch von einer Basis trennen, die er nicht mehr benötigt.
Angenommen, featureY wurde von featureX abgezweigt, ist aber tatsächlich unabhängig von den Änderungen in featureX und gehört zu master:
o---o---o featureY
/
o---o---o---o featureX
/
o---o---o---o masterAusführen:
git rebase --onto master featureX featureYHier ist featureX die <oldbase>, master ist die <newbase> und featureY ist der Branch, der rebasiert wird. Git spielt nur die eigenen Commits von featureY auf master neu ab und trennt sie von featureX:
o'--o'--o' featureY
/
o---o---o---o---o master
\
o---o---o---o featureXKonflikte während eines Rebase lösen
Da Rebase Ihre Commits einzeln neu anwendet, kann ein Konflikt den Prozess bei jedem Commit unterbrechen. Wenn das passiert, hält Git an und teilt Ihnen mit, welche Dateien Konflikte haben.
Der Workflow, um durchzukommen:
# 1. fix the conflicted files in your editor, then stage them
git add <resolved-file>
# 2. continue replaying the remaining commits
git rebase --continueWeitere Steuerungsmöglichkeiten, wenn ein Rebase pausiert ist:
git rebase --skip— den aktuellen Commit überspringen und fortfahren (mit Vorsicht verwenden; die Änderungen dieses Commits gehen verloren).git rebase --abort— alles stoppen und den Branch genau dorthin zurücksetzen, wo er vor dem Start war.
Ein langlebiger Branch, der weit von master abgewichen ist, erzeugt die meisten Konflikte, manchmal denselben Konflikt bei mehreren Commits. Zwei Gewohnheiten reduzieren den Aufwand: häufig gegen master rebasen statt nur einmal am Ende, und Commits klein und fokussiert halten.
Konfigurationsoptionen
Einige Rebase-Standardeinstellungen können mit git config festgelegt werden. Diese ändern das Verhalten von git rebase und seine Ausgaben:
rebase.stat— ein boolean (Standardfalse), der einen visuellen Diffstat der Änderungen seit dem letzten Rebase umschaltet.rebase.autoSquash— ein boolean, der das--autosquash-Verhalten umschaltet (automatisches Umsortieren vonfixup!/squash!-Commits beim interaktiven Rebase).rebase.missingCommitsCheck— steuert, was passiert, wenn Commits aus der Todo-Liste entfernt werden. Akzeptiert einen dieser Werte:
| Wert | Verhalten |
|---|---|
ignore | Der Standard. Warnungen zu fehlenden Commits werden ignoriert. |
warn | Im interaktiven Modus wird eine Warnung über entfernte Commits ausgegeben. |
error | Der Rebase stoppt und gibt Warnmeldungen zu entfernten Commits aus. |
rebase.instructionFormat— ein string im git log-Format, der verwendet wird, um jede Commit-Zeile in der interaktiven Todo-Liste zu formatieren.
Wiederherstellung nach einem misslungenen Rebase
Ein Rebase kann destruktiv wirken: Mit squash oder drop verschwinden Commits aus Ihrem Branch-Log, und es sieht so aus, als wären sie für immer verloren. Das sind sie nicht. Git führt in der git reflog einen Protokolleintrag, wo Ihr Branch vor jeder Operation zeigte.
Um einen Rebase rückgängig zu machen, finden Sie den Eintrag von kurz davor und setzen Ihren Branch darauf zurück:
# see where the branch was before the rebase
git reflog
# example output:
# a23db19 HEAD@{0}: rebase (finish): returning to refs/heads/feature
# 31d332c HEAD@{5}: rebase (start): checkout master
# c0ffee1 HEAD@{6}: commit: the state you want back
# move the branch back to the pre-rebase commit
git reset --hard HEAD@{6}Dies ist Ihr Sicherheitsnetz — solange Sie das Reflog lesen können, ist kein Rebase wirklich unumkehrbar.
Wiederherstellung nach einem Upstream-Rebase
Wenn ein Teammitglied einen Branch rebasiert und per Force-Push überträgt, den Sie ebenfalls bearbeiten, wird ein normales git pull versuchen, Ihre Commits mit dem umgeschriebenen Remote-Tip abzugleichen, was zu einer duplizierten oder verworrenen Historie führen kann.
Die Lösung verwendet das Reflog des Remote-Tracking-Branches, um zu finden, wo er vor dem Rebase zeigte, und spielt dann Ihre Arbeit mit --onto auf den neuen Tip neu ab:
# find the old tip of origin/feature in the remote-tracking reflog
git reflog show origin/feature
# replay your local commits from the old base onto the new one
git rebase --onto origin/feature <old-origin-tip> featureDadurch werden nur Ihre Commits auf den per Force-Push übertragenen Tip verschoben, ohne die alten, jetzt umgeschriebenen Commits mitzuziehen.
Verwandte Themen
- git merge — die Alternative ohne Umschreiben zur Integration von Branches.
- git reflog — Ihr Rückgängig-Protokoll zur Wiederherstellung nach einem fehlerhaften Rebase.
- git reset — einen Branch-Pointer verschieben, auch zurück zu einem Zustand vor dem Rebase.
- git cherry-pick — einzelne Commits neu abspielen, ohne einen ganzen Branch zu rebasen.