Unterschied zwischen git merge und git rebase

By | 23. März 2017

Es gibt immer wieder Entwickler, denen der genaue Unterschied zwischen git merge und git rebase nicht ganz klar. Daher habe ich mir etwas Zeit genommen mal etwas auf die Unterschiede einzugehen. Als kleine Warnung vorweg, es handelt sich hierbei nicht um Expertenwissen mit einer extremen Tiefe. Es soll einfach nur grob die Unterschiede klar machen. Dabei wird es ziemlich vereinfacht dargestellt.

Unterschied zu CVS/SVN

Viele die aktuell mit git arbeiten haben mit hoher Wahrscheinlichkeit davor mit CVS und/oder SVN gearbeitet. Daher ist es vielleicht sinnvoll mal auf einen speziellen Unterschied zwischen CVS/SVN und GIT einzugehen. Genauer gesagt um die Form bzw. Art und Weise der Commits.

SVN/CVS -> Dateibasiert

Wenn man eine Datei verändert kann man in SVN und CVS commiten, ohne vorher (entfernte) Änderungen an anderen Dateien vom Repository zu holen.

GIT -> Commitbasiert

Bei GIT funktioniert dies so natürlich nicht. Wenn man etwas auf einen remote pushen möchte muss man zuerst alle Commits lokal haben uns seinen Commit hinten heranhängen. Mit anderen Worten man muss erst alle (entfernten) Änderungen holen, bevor man seine veröffentlichen kann.

Ausgangspnkt

Ausgangspunkt

Ausgangspunkt

Wir betrachten eine Ausgangssituation mit 3 commits, die chronologisch nacheinander gepusht wurden. Ohne jegliche Abzweigungen oder andere besondere Beschaffenheiten.

Konflikt

Konflikt

Konflikt

Nun haben wir den Fall dass zwei Entwickler gleichzeitig etwas entwickeln. Dazu haben beide Entwickler mit dem Stand von C angefangen. Nun war Entwickler D schneller und konnte seine Änderungen vorher commiten und anschließend pushen. Dadurch wurde der Commit C ganz normal an den Graphen angehängt. Sobald Entwickler E nun seine Änderungen durchgeführt hat, commitet hat und pushen möchte hat er ein Problem. Das remote Repository ist schon weiter als zudem Stand als Entwickler E sein lokales Repository aktualisiert hat und auf dieser Basis E entwickelt hat. Er wird nun vom remote Repository dazu aufgefordert zuerst die Änderungen ebenfalls lokal zu übernehmen und seine eigenen Änderungen in diese zu integrieren. Hierfür hat er nun drei Möglichkeiten, wobei es in der Realität nur zwei sind. Dazu gehören git pull, git rebase und git merge. Hierbei stellt git pull eine Ausnahme dar. Denn im Grunde ist der besagte Befehl nur eine Aneinanderkettung von zwei anderen Befehlen, und zwar git fetch + git merge oder git fetch + git rebase. In der default Konfiguration von GIT ist ersteres der Beiden Methoden eingestellt, kann natürlich aber jederzeit auf die zweite Variante umkonfiguriert werden.

Methode 1: Merge

Merge

Merge

Die erste Möglichkeit, die dem Entwickler E zur Verfügung steht ist der sogenannte git merge. Hierbei wird mittels git fetch der neue Commit C geholt und mit dem eigenen Commit E zusammengeführt. Dabei entsteht ein neuer Commit, in diesem Fall M. Das Problematische an M ist nun dass es sich hierbei um einen sogenannten “trivialen” Commit handelt. Mit anderen Worten um einen Commit ohne Änderungen an irgendwelchen Dateien. Er kennzeichnet lediglich dass es hier einen Merge gab. Des Weiteren entsteht hier auch eine unschöne Abzweigung.

Methode 2: Rebase

Rebase

Rebase

Die zweite Möglichkeit ist an dieser Stelle ein git rebase zu machen. Hierbei macht nun git folgendes: es verhält sich so als hätten man erst nach D abgezweigt und auf der Basis von D entwickelt. Somit wird der commit E als solches gelöscht und ein neuer Commit R generiert, welcher die Änderungen von E in der Gänze enthält, ebenfalls aber auch die Änderungen von D berücksichtigt. Somit erhält man eine flache Historie ohne Abzweigungen und ohne triviale Commits.

Merge vs. Rebase

Merge

Rebase

Wann rebase und wann merge verwenden?

Das ist prinzipiell garnicht so einfach zu sagen aber wenn man es schon allgemein Ausdrücken möchte könnte wohl am besten Folgende Faustregel passen:

Rebase dann verwenden wenn folgende Aussage zutrifft: “Hätte ich bloß später gefetcht.”

Grob kann man auch sagen dass ein git rebase im Fall von lokalen und entfernten Änderungen auf dem selben Branch sinnvoller ist. Während es sinnvoller ist git merge zu verwenden wenn man öffentliche Branches zusammenführen will.

Dabei gilt folgendes Tabu: git rebase niemals auf öffentliche Branches anwenden. Zum Glück handelt es sich bei unseren lokalen Änderungen stets auch um lokale und somit nicht öffentliche Branches.

Wie arbeitet ihr am liebsten mit GIT? Habt ihr eine andere Meinung zu diesem Thema? Dann nichts wie ‘raus damit. Ich freue mich über jeden Kommentar.

Ein Kommentar zu “Unterschied zwischen git merge und git rebase

  1. Frank Zweig

    Aha! Man lernt eben nie aus – der Unterschied war mir nicht so klar und Euer Bericht hat da endlich mal so richtig Licht ins Dunkel gebracht sozusagen… 🙂

    Besten Dank!

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.