Git Tutorium – Teil 3
Klarer wird es, wenn man sich die Commits auf einem Branch als einen Stapel vorstellt. Beim Rebase wird auf more_content
sozusagen jeder Commit vom Stapel genommen, bis man einen gemeinsamen Commit vom Branch master
gefunden hat. An diesem Punkt werden dann die neuen Commits von master
wieder auf more_content
gestapelt. Anschließend werden die vorläufig entfernten Commits auf more_content
wieder einzeln auf den Commit-Stapel gelegt.
Jetzt lohnt sich ein Blick in das Log. Relevant sind lediglich die letzten drei Commits, welche man sich mit dem Parameter -n 3
für den aktuellen Branch anzeigen lassen kann.
$ git log -n 3 commit 27bf2ae348279599cfa67fd0631e7f3e5c90840d Author: Sujeevan Vijayakumaran <mail@svij.org> Date: Sun Jan 4 19:03:23 2015 +0100 Verdreifachung des Lorem-Ipsum-Texts commit 8d8d6ce271ddf776def806bbe65c1439c84f8c67 Author: Sujeevan Vijayakumaran <mail@svij.org> Date: Sun Jan 4 19:12:42 2015 +0100 Navigation um zwei Links erweitert. commit aa2fbe6716f743d434a0f7bec9b97548304338c8 Merge: b967fa1 b6781c8 Author: Sujeevan Vijayakumaran <mail@svij.org> Date: Sun Jan 4 15:54:15 2015 +0100 Merge branch 'titel' Conflicts: index.html
Im Git-Log steht oben immer der neueste Commit auf dem Branch. Wer jetzt allerdings genau hinsieht, merkt, dass der oberste Commit um 19:03 Uhr getätigt wurde und der Commit darunter um 19:12 Uhr. Zeitlich betrachtet ist also der vorletzte Commit der neueste Commit, während der echte neueste Commit zeitlich vorher erzeugt wurde. Dies ist eine Eigenschaft, die genau dann beim Rebasen zustande kommt. In der Historie eines Git-Repositorys sind die Commits nämlich immer in logische Reihenfolge und diese ist nicht zwangsläufig auch die zeitlich richtige Reihenfolge. Es stellt sich für viele vermutlich an dieser Stelle die Frage: Warum brauche ich das?
Beim Entwickeln von Software werden häufig einzelne Features gleichzeitig entwickelt. Wenn etwa der Branch master
nur vollständige und somit fertige Features enthält, dann werden dort immer nur die Änderungen zusammengeführt, wenn die Branches fertig sind. Wenn man allerdings an einem größeren Feature entwickelt, welches durchaus längere Zeit braucht, dann zweigt man beispielsweise vom Branch master
ab und entwickelt für eine Zeit dort sein Feature. Über die Zeit hinweg läuft allerdings auch die Entwicklung auf dem Branch master
weiter, was heißt, dass diese beiden Entwicklungszweige gegebenenfalls immer stärker divergieren. Ein konfliktfreies Mergen beider Branches nach längerer Entwicklungszeit ist dann gegebenenfalls nicht mehr so einfach möglich. Wenn man nun auf dem Entwicklungsbranch ein Rebase durchführt, dann sind da auch alle Änderungen von master
enthalten. Dieses Vorgehen ist auch dann sinnvoll, wenn der Entwickler auf dem Entwicklungsbranch die Änderungen aus master
braucht. Unschön wäre hier ein Merge, da man in der Historie beim mehrmaligen Mergen von master
diverse Merge-Commits besitzt, die man durch das Rebasen einfach vermeiden kann.
Nach dem Rebase möchte man die Änderungen vom Branch more_content
letztendlich auch in master
übernehmen. Hierfür reicht dann wieder ein normaler Merge:
$ git checkout master $ git merge more_content Aktualisiere 8d8d6ce..27bf2ae Fast-forward index.html | 6 ++++++ 1 file changed, 6 insertions(+)
Der Merge ist dann ein Fast-Forward Merge. Wenn man nun erneut in das Git Log von master
schaut, dann sieht man keinerlei Informationen mehr von der Existenz des Branches more_content
. Rebasing lohnt sich also auch für Experimentier-Branches, dessen Namen man hinterher nicht mehr in der Historie lesen möchte.
Zum Schluss stellt sich noch die Frage, wann man Rebasen und wann man Mergen sollte. Als kleine Grundregel kann man sich merken, dass man immer dann Rebasen sollte, wenn man zeitgleich laufende Änderungen regelmäßig aus einem anderen Branch auch in seinen eigenen Entwicklungsbranch hineinholen möchte. Ein Merge sollte man hingegen dann machen, wenn man fertige Entwicklungsbranches in einen der Hauptentwicklungsbranches zusammenführen möchte. Weder das eine noch das andere lässt sich problemlos jedes Mal durchführen, sodass es häufig auch auf die jeweilige Situation ankommt, ob man nun rebased oder mergt.