Interaktives Rebase wird manchmal als das „Schweizer Taschenmesser“ von Git bezeichnet – weil es so viele verschiedene Werkzeuge für so viele verschiedene Anwendungsfälle enthält! Es gibt jedoch einen Hauptanwendungsfall: das Bereinigen der lokalen Commit-Historie.
Merken Sie sich das Wort „lokal“: es sollte nur zum Bereinigen Ihrer eigenen, lokalen Commit-Historie verwendet werden, zum Beispiel bevor Sie einen Ihrer Feature-Zweige in einen Team-Zweig integrieren. Im Gegensatz dazu sollte es NICHT für die Commit-Historie verwendet werden, die bereits in einem entfernten Repository gepusht und freigegeben wurde. Interaktives Rebase ist eines der Werkzeuge, die die Git-Historie „umschreiben“ – und das sollten Sie nicht bei Commits tun, die bereits mit anderen geteilt wurden.
Nachdem diese kleine Warnung aus dem Weg geräumt ist, lassen Sie uns einige praktische Beispiele betrachten!
Hinweis: Zur besseren Veranschaulichung der Szenarien und Arbeitsabläufe in diesem Beitrag habe ich in einigen meiner Screenshots die Git-Desktop-GUI „Tower“ verwendet.
Korrigieren einer alten Commit-Nachricht
Manchmal fällt einem ein Tippfehler in einer alten Commit-Nachricht auf – oder man hat vergessen, in der Beschreibung etwas zu erwähnen, das erwähnenswert ist. Wenn es sich um den allerletzten Commit handeln würde, hätten wir einfach die Option --amend
des Befehls git commit
verwenden können. Aber für ältere Commits müssen Sie interaktives Rebase verwenden, um sie nachträglich zu ändern.
Hier ist ein Beispiel für eine schrecklich schief gelaufene Commit-Nachricht, die wir korrigieren wollen:
Eine schlechte Commit-Nachricht, die korrigiert werden muss
Der erste Schritt in jeder interaktiven Rebase-Sitzung ist es, zu bestimmen, welchen Teil der Commit-Historie Sie manipulieren wollen. Um das obige Beispiel noch einmal aufzugreifen: Um diesen schlechten Commit zu ändern, müssen wir die Sitzung bei seinem Eltern-Commit beginnen.
Start unserer interaktiven Rebase-Sitzung
Wir können nun den Hash dieses Start-Commits in den interaktiven Rebase-Befehl einspeisen:
$ git rebase -i 0023cddd
Ein Editor-Fenster wird sich nun öffnen, das eine Liste der Commits enthält, die Sie gerade zur Bearbeitung ausgewählt haben. Und wundern Sie sich nicht, denn sie sind in umgekehrter Reihenfolge: In einer interaktiven Rebase-Sitzung wendet Git die alten Commits wieder an, Element für Element – was bedeutet, dass die Umkehrung der Reihenfolge aus der Sicht von Git korrekt ist.
Editor-Fenster mit den ausgewählten Commits
Eine weitere wichtige Anmerkung zu diesem Editor-Fenster: Sie führen hier nicht die eigentlichen Manipulationen durch! Oder, in diesem konkreten Beispiel, ändern Sie hier NICHT die Commit-Nachricht. Stattdessen markieren Sie nur die Übergabe, die Sie ändern wollen, mit einem Aktionsschlüsselwort. In unserem Fall, weil wir die Nachricht eines Commits ändern wollen, markieren wir die Zeile mit „reword“. Wenn Sie dann speichern und das Editorfenster schließen, öffnet sich ein neues Fenster, das die alte Commit-Nachricht enthält. Jetzt ist es an der Zeit, die Änderungen vorzunehmen:
Endlich können wir unsere Änderungen vornehmen
Nach dem erneuten Speichern und Schließen ist die interaktive Rebase-Sitzung abgeschlossen und unsere alte Commit-Nachricht wurde korrigiert!
Mehrere Commits zu einem zusammenfassen
Ein weiterer Anwendungsfall für interaktives Rebase ist, wenn Sie mehrere alte Kommentare zu einem zusammenfassen wollen. Dabei gilt natürlich die goldene Regel der Versionskontrolle: In den meisten Situationen ist es vorteilhaft, mehr und kleinere Commits zu erstellen, anstatt ein paar große. Aber wie bei allem können wir feststellen, dass wir es übertrieben haben und nun zwei oder mehr alte Commits zu einem einzigen verschmelzen wollen.
Um ein konkretes Beispiel zu geben, sagen wir, wir wollen die folgenden ausgewählten Commits zu einem einzigen zusammenfassen:
Lassen Sie uns mehrere Commits zu einem zusammenfassen
Genauso wie in unserem ersten Fall beginnen wir damit, die interaktive Rebase-Sitzung mindestens beim übergeordneten Commit desjenigen zu starten, den wir manipulieren wollen.
$ git rebase -i 2b504bee
Auch hier öffnet sich ein Editor-Fenster, das den Teil der Commit-Historie auflistet, den wir manipulieren wollen:
Zeilen mit „squash“ markieren“
Das Aktions-Schlüsselwort, das wir hier verwenden werden, heißt „squash“. Und es gibt nur eine wichtige Information, die Sie über „squash“ wissen müssen, um es zu verwenden: Die Zeile, die wir mit dem Schlüsselwort „squash“ markieren, wird mit der Zeile direkt darüber kombiniert. Deshalb habe ich, wie Sie in meinem Screenshot oben sehen können, die Zeile Nr. 2 mit „squash“ markiert, um sie mit der Zeile Nr. 1 zu kombinieren.
Wir können nun speichern und das Editorfenster schließen und wieder zusehen, wie ein neues Fenster erscheint: Wir werden nun aufgefordert, eine Commit-Nachricht für die neue Commit einzugeben, die durch die Kombination der beiden alten Commits entsteht.
Eingabe einer neuen Nachricht für den neuen, zerquetschten Commit
Nach dem Speichern und Schließen dieses Editorfensters werden Sie sehen, dass ein neuer Commit erstellt wurde, der die Changesets der beiden alten Commits enthält. Voila!
Fixing a mistake
Ein weiterer Anwendungsfall für interaktives Rebase ist, wenn Sie einen Fehler in einem Ihrer früheren Commits gefunden haben. Dabei spielt es keine Rolle, was genau Sie verbockt haben: Sie könnten vergessen haben, eine bestimmte Änderung hinzuzufügen, hätten eine Datei löschen sollen oder einfach einen Tippfehler eingebaut haben…
Die natürliche Tendenz ist es, in einer solchen Situation einfach einen neuen Commit zu erstellen, der den Fehler korrigiert. Aber auf der anderen Seite bringt das unsere Commit-Historie durcheinander: einen ursprünglichen Commit zu erstellen und dann einen „Pflaster“-Commit hinzuzufügen, nur um ein paar Fehler zu korrigieren… das ist eine chaotische Art zu arbeiten. Ihre Commit-Historie wird bald schwer zu verstehen sein, weil sie mit all diesen kleinen „Quick-Fix-Commits“ übersät ist!
An dieser Stelle kommt „fixup“, eines der Werkzeuge, die mit interaktivem Rebase geliefert werden, sehr gelegen. Fixup nimmt diesen „Quick Fix“-Commit, wendet seine Änderungen auf den ursprünglichen Commit an (und korrigiert ihn dadurch) und wird dann den Pflaster-Commit los:
Wie „fixup“ funktioniert
Nachdem wir fertig sind, sieht es so aus, als hätte es nie ein Problem mit unserem ursprünglichen Commit gegeben! Lassen Sie uns das anhand eines praktischen Beispiels durchgehen.
Der erste Schritt besteht darin, alles zu tun, was notwendig ist, um das Problem zu beheben: Das kann bedeuten, eine neue Datei hinzuzufügen, Änderungen an bestehenden Dateien vorzunehmen, veraltete Dateien zu löschen … Sie müssen „nur“ die Änderungen vornehmen, die den Fehler korrigieren.
Der nächste Schritt besteht darin, diese Änderungen an das Repository zu übergeben – allerdings mit einem kleinen Extra: Beim Übertragen verwenden wir das --fixup
-Flag und teilen Git den Commit-Hash unseres fehlerhaften Commits mit:
$ git add corrections.txt$ git commit --fixup 2b504bee
Wenn Sie nun einen Blick auf die Commit-Historie werfen, werden Sie sehen, dass ein ziemlich normal aussehender Commit erstellt wurde – wahrscheinlich nicht die Magie und das Feuerwerk, das Sie erwartet hätten. Aber wenn Sie einen genaueren Blick darauf werfen, werden Sie sehen, dass etwas vor sich geht: dem neuen Commit wurde automatisch „fixup !“ und der Commit-Betreff unseres schlechten Commits vorangestellt.
Der ursprüngliche Commit und der Fix-Commit
Der dritte Schritt besteht nun darin, die interaktive Rebase-Sitzung zu starten. Wieder wählen wir den Elternteil unseres schlechten Commits als Startpunkt…
$ git rebase -i 0023cddd --autosquash
… und als zweiten Teil der geheimen Sauce verwenden wir das --autosquash
Flag. Diese Option sorgt dafür, dass wir in dem nun geöffneten Editor-Fenster nichts mehr tun müssen. Schauen Sie sich die Situation genau an:
Unser Fix-Commit ist als „fixup“ markiert und an die richtige Position sortiert
Sie werden sehen, dass Git automatisch zwei Dinge für uns getan hat:
- Es hat unseren Band-Aid-Commit als „fixup“ markiert.“
- Es hat die Zeilen neu sortiert, so dass unser Band-Aid-Commit direkt unter unserem schlechten Commit erscheint. Das liegt daran, dass „fixup“ genau wie „squash“ funktioniert, indem es mit der Zeile darüber kombiniert wird.
Mit anderen Worten: Es bleibt uns nichts anderes übrig, als zu speichern und das Editor-Fenster zu schließen.
Werfen wir noch einen Blick auf die Commit-Historie:
Ein glückliches Ende!
Nicht nur, dass unser ursprünglich schlechter Commit nun die Änderungen aus unserem Band-Aid-Commit enthält. Darüber hinaus ist der hässliche Commit aus der Commit-Historie verschwunden! Alles ist schön sauber, so als ob es nie ein Problem gegeben hätte!
Entdecken Sie die Macht des interaktiven Rebase
Es gibt viele Anwendungsfälle für interaktives Rebase – und die meisten davon in der Abteilung „Fehler beheben“. Für einen Überblick über andere nützliche Dinge, die Sie tun können, empfehle ich das kostenlose „First Aid Kit for Git“: Es ist eine Sammlung von kurzen Videos (2-3 Minuten pro Episode), die Ihnen helfen, Fehler mit interaktivem Rebase und anderen Git-Tools rückgängig zu machen.
Anmerkung des Herausgebers: Ich musste interaktives Rebase verwenden, als ich diesen Beitrag überarbeitete! Einer meiner Commits enthielt ein Bild, das größer als 1 MB war, was gegen die Regeln für GitLab-Websiteprojekte verstößt. Ich musste zurückgehen und den Commit korrigieren, um stattdessen ein Bild in der richtigen Größe einzufügen. Danke für die Lektion, Universum! 😁
Weitere Git-Tipps und -Tricks
- 15 Git-Tipps zur Verbesserung Ihres Arbeitsablaufs
- Mit Git Partial Clone holen Sie nur die große Datei, die Sie benötigen
- Git happens! 6 häufige Git-Fehler und wie man sie behebt
Über den Gastautor
Tobias Günther ist der Geschäftsführer von Tower, dem beliebten Git-Desktop-Client, der mehr als 100.000 Entwicklern auf der ganzen Welt hilft, mit Git produktiver zu arbeiten.
Coverbild von David Taljat auf Pexels