Git: Merging vs. Rebasing (Teil 1)

Der Befehl git rebase hat einen gewissen Ruf als Kommando für Fortgeschrittene, das Git-Einsteiger meiden sollten. Doch git rebase kann einem Entwicklungsteam das Leben deutlich leichter machen, wenn es sorgsam verwendet wird. In diesem Beitrag und folgenden Artikeln wollen wir git rebase mit git merge vergleichen.

Konzeptioneller Überblick

Zunächst müssen wir verstehen, dass git rebase dasselbe Problem wie git merge löst. Beide Befehle dienen dazu, Änderungen von einem Branch in einen anderen Branch zu integrieren, nur nutzen sie unterschiedliche Wege.

Nehmen wir an, wir beginnen mit der Arbeit an einem neuen Feature in einem dedizierten Branch, und währenddessen aktualisiert ein anderes Teammitglied den master-Branch mit neuen Commits. Das Ergebnis ist eine geforkte Historie – etwas, mit dem jeder vertraut ist, der Git schon als Kollaborationswerkzeug eingesetzt hat.

Git Forked History

Eine geforkte Historie

Nun gehen wir davon aus, dass die neuen Commits im master relevant für das Feature sind, an dem wir arbeiten. Um sie in unseren feature-Branch einzubinden, haben wir zwei Optionen: mergen oder rebasen.

Die Merge-Option

Die einfachste Möglichkeit besteht darin, den master-Branch in den feature-Branch zu mergen, was so aussehen könnte:

git checkout feature
git merge master

Oder auf einen Einzeiler komprimiert:

git merge master feature

Das erzeugt einen Merge-Commit in den feature-Branch, der die Historien beider Branches vereint. So erhalten wir eine Branch-Struktur wie diese:

Git Merging

Mergen des Master-Branchs in den Feature-Branch

Mergen ist gut, weil es eine nicht-destruktive Operation ist. Die bestehenden Branches werden auf keine Weise verändert. Dadurch können wir die potenziellen Fallgruben des Rebasings umgehen, siehe unten.

Andererseits bedeutet das auch, dass der feature-Branch jedes Mal, wenn wir Upstream-Änderungen integrieren müssen, einen irrelevanten Merge-Commit erhält. Wenn im master viel Aktivität herrscht, wird die History unseres feature-Branchs schnell zugemüllt. Es ist zwar möglich, dieses Problem mithilfe der Optionen von git log zu minimieren, aber für andere Entwickler ist es schwierig, die Historie des Projekts zu verstehen.

Die Rebase-Option

Als Alternative zum Mergen können wir den feature-Branch auf den master-Branch rebasen, wofür wir die folgenden Befehle nutzen:

git checkout feature
git rebase master

Damit bewegen wir den kompletten feature-Branch an die Spitze des master-Branchs und integrieren all die neuen Commits im master. Doch statt einen Merge-Commit zu nutzen, schreibt das Rebasen die Projekthistorie neu, indem für alle Commits im Original-Branch brandneue Commits erstellt werden.

Git Rebasen

Rebasing des Feature-Branchs auf den Master-Branch

Der Hauptvorteil des Rebasings ist eine viel sauberere Projekthistorie. Erstens eliminiert es die unnötigen Merge-Commits, die git merge erforderlich macht. Zweitens führt Rebasing zu einer perfekt linearen Projekthistorie, wie das Diagramm oben zeigt – wir können von der Spitze des feature-Branchs bis zum Anfang des Projekts zurückgehen und werden keinen Forks begegnen. Das erleichtert es, mit Befehlen wie git log, git bisect und gitk durch das Projekt zu navigieren.

Allerdings tauschen wir zwei Dinge gegen diese makellose Commit-Historie ein: Sicherheit und Rückverfolgbarkeit. Wenn wir die goldene Regel des Rebasings nicht befolgen (siehe den Folgeartikel), kann das Neu-Schreiben der Projekthistorie potenziell katastrophale Folgen für unseren Kollaborations-Workflow haben. Und darüber hinaus fehlt beim Rebasing der Kontext, den ein Merge-Commit bietet – wir können nicht sehen, wann Upstream-Änderungen in das Feature integriert wurden.

Interaktives Rebasing

Interaktives Rebasing bietet uns die Möglichkeit, Commits zu modifizieren, wenn sie in den neuen Branch bewegt werden. Das ist noch mächtiger als ein automatisches Rebasing, denn wir haben dabei die vollständige Kontrolle über die Commit-Historie des Branchs. Diese Option wird häufig genutzt, um eine unordentliche Historie aufzuräumen, ehe ein feature-Branch in den master gemergt wird.

Um eine interaktive Rebasing-Session zu beginnen, nutzen wir git rebase mit der Option i:

git checkout feature
git rebase -i master

Damit öffnen wir einen Texteditor, der alle Commits auflistet, die bewegt werden können:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

Diese Liste definiert exakt, wie der Branch nach dem Rebasing aussehen wird. Durch die Änderung des pick-Befehls und/oder die Umsortierung der Einträge können wir die Branch-Historie so gestalten, wie wir es gerne möchten. Wenn der zweite Commit beispielsweise ein kleines Problem im ersten Commit fixt, können wir mit fixup beide in einem einzelnen Commit zusammenfassen:

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

Wenn wir speichern und die Datei schließen, führt Git das Rebasing gemäß unseren Anweisungen aus. Die Projekthistorie hat anschließend diese Form:

Git interaktives Rebasing

Das Eliminieren nicht signifikanter Commits wie hier macht die Historie des Features viel verständlicher. git merge vermag das nicht.

Im Folgeartikel wenden wir uns dann der angesprochenen goldenen Regel des Rebasings zu.

Weiterführende Infos: Ihr Partner für Git und Stash

Kennen Sie Stash, Atlassians Git-Repository-Managementsystem? Stash bietet eine zentrale Lösung zum Management des gesamten distributierten Codes: Hier kommen alle Git-Repositories im Unternehmen zusammen, hier finden Entwickler immer die letzte offizielle Version eines Projekts, hier können Projektverantwortliche Berechtigungen kontrollieren, um sicherzustellen, dass die richtigen Nutzer Zugriff auf den richtigen Code haben.

Möchten Sie mehr erfahren? Wir sind offizieller Vertriebspartner von Atlassian und einer der größten Atlassian Experts Partner weltweit. Gerne unterstützen wir Sie bei der Evaluierung, Lizenzierung und Adaption von Stash. Und wenn Sie Atlassian-Lizenzen bei //SEIBERT/MEDIA kaufen, gewähren wir Ihnen einen Rabatt in Höhe von 10% der Lizenzkosten in Form von Beratungsleistungen. Bitte sprechen Sie uns einfach an.

99 Argumente für Stash als Git-Repository-Manager
Branch-basierte Git-Workflows mit Stash adaptieren
Echte Integration: Das Zusammenspiel von JIRA, Stash und Bamboo
Interview: Die Vorteile von Git in der Software-Entwicklung und die Möglichkeiten von Stash
So funktioniert die Lizenzierung von Atlassian-Produkten