Git rebase#

Die Befehle git rebase und git merge ermöglichen das Zusammenführen von Git-Verzweigungen. Während git merge immer ein sich vorwärtsbewegender Änderungsansatz ist, verfügt git rebase über leistungsfähige Funktionen zum Umschreiben der Historie. Hier wollen wir die Konfiguration, Anwendungsfälle und Fallstricke genauer betrachten.

Dabei verschiebt git rebase eine Folge von Commits zu einem neuen Basis-Commit und kann so für Feature-Branches-Workflows nützlich sein. Intern erreicht Git dies, indem es neue Commits erstellt und diese auf die angegebene Basis anwendet; die gleichaussehenden Commits von Zweigen sind also völlig neue Commits.

Der Hauptgrund für git rebase ist, einen linearen Projektverlauf aufrechtzuerhalten. Wenn sich der Hauptzweig weiterentwickelt hat, seit ihr mit der Arbeit an einem Funktionszweig begonnen habt, wollt ihr vielleicht die letzten Aktualisierungen des Hauptzweigs in eurem Funktionszweig erhalten, aber die Historie eures Zweigs sauber halten. Dies hätte den Vorteil, dass ihr später ein sauberes git merge eures Funktionszweiges in den Hauptzweig durchführen könntet. Diese saubere Historie erleichtert euch auch, eine Regression mit Regressionen finden mit git bisect zu finden. Ein realistischeres Szenario wäre folgendes:

  1. Im Hauptzweig wird ein Fehler in einer Funktion festgestellt, die früher einmal fehlerfrei funktionierte.

  2. Durch die saubere Historie des Hauptzweigs sollte Git Log schnell Rückschlüsse ermöglichen.

  3. Sollte Git Log nicht zum gewünschten Ergebnis führen, hilft vermutlich git bisect weiter. Dabei hilft git bisect die saubere Git-Historie bei der Suche nach der Regression.

Warnung

Die veröffentlichte Historie sollte nur in sehr seltenen Ausnahmefällen geändert werden, da die alten Commits durch neue ersetzt und es so aussehen würde, als wäre dieser Teil der Projektgeschichte plötzlich verschwunden.

Bemerkung

git rebase wird auch kurz in Jupyter Notebooks unter Git und Feature-Branches behandelt

Rebase abhängiger Zweige mit –update-refs#

Wenn ihr an einem großen Feature arbeitet, ist es oft hilfreich, die Arbeit auf mehrere Zweige zu verteilen, die aufeinander aufbauen.

Diese Zweige können jedoch umständlich zu verwalten sein, wenn ihr den Verlauf in einem früheren Zweig überschreiben müsst. Da jeder Zweig von den vorherigen Zweigen abhängt, führt das Umschreiben von Commits in einem Zweig dazu, dass die nachfolgenden Zweige nicht mehr mit der Historie verbunden sind.

Git 2.38 wird mit einer neuen --update-refs-Option für git rebase ausgeliefert, die solche Aktualisierungen für euch durchführt , ohne dass ihr jeden einzelnen Zweig manuell aktualisieren müsst und ohne dass die nachfolgenden Zweige ihre Historie verlieren.

Wenn ihr diese Option bei jedem Rebase verwenden möchtet, könnt ihr git config --global rebase.updateRefs true ausführen, damit sich Git so verhält, als ob die Option --update-refs immer angegeben ist.

Commits mit rebase löschen#

$ git rebase -i SHA origin/main

-i interaktiver Modus, in dem euer Standardeditor geöffnet wird und eine Liste aller Commits nach dem zu entfernenden Commit mit dem Hash-Wert SHA angezeigt wird, z.B.:

pick d82199e Update readme
pick 410266e Change import for the interface

Wenn ihr nun eine Zeile entfernt, so wird dieser Commit nach dem Speichern und Schließen des Editors gelöscht. Anschließend kann das entfernte Repository aktualisiert werden mit:

$ git push origin HEAD:main -f

Ändern einer Commit-Nachricht mit rebase#

Dies lässt sich ebenfalls einfach mit rebase realisieren wobei ihr in eurem Editor nicht die Zeile löschen sondern in der Zeile pick durch r (reword) ersetzen müsst.