Git: Merging vs. Rebasing (Teil 3)

In den beiden ersten Beiträgen dieser Artikelreihe (Teil 1, Teil 2) haben wir uns mit konzeptionellen Fragen rund um git merge vs. git rebase auseinandergesetzt und Möglichkeiten besprochen, um das Rebasing sinnvoll in den Entwicklungs-Workflow mit Git einzubinden. Darauf aufbauend folgen hier nun weitere Anwendungsfälle.

Upstream-Änderungen in ein Feature einbinden

Im konzeptionellen Überblick haben wir gesehen, wie ein feature-Branch Upstream-Änderungen vom master integrieren kann, indem entweder git merge oder git rebase zum Einsatz kommt. Merging ist eine sichere Option, die die gesamte Historie unseres Repos bewahrt, während Rebasing eine lineare Historie erzeugt, indem unser feature-Branch an die Spitze des master-Branchs bewegt wird.

Diese Verwendung von git rebase ist die gleiche wie beim lokalen Aufräumen (und kann simultan ausgeführt werden), aber in unserem Prozess integriert das Rebasing nun Upstream-Commits vom master.

Vergessen wir nicht, dass es absolut legitim ist, auf einen Remote-Branch zu rebasen. Das kann passieren, wenn wir mit Kollegen am selben Feature zusammenarbeiten und die Änderungen der Anderen in unser Repository integrieren müssen.

Nehmen wir an, wir arbeiten gemeinsam mit John an einer Funktion. Wenn wir und John Commits zum feature-Branch hinzugefügt haben, wird unser Repository, nachdem wir den Remote-feature-Branch aus Johns Repo gefetcht haben, in etwa so aussehen:

Git Collaboration 1

Zusammenarbeit am selben Feature-Branch

Diesen Fork können wir auf exakt die gleiche Weise auflösen wie bei der Integration von Upstream-Änderungen vom master: Entweder mergen wir unseren lokalen Feature-Branch mit john/feature oder wir rebasen ihn an die Spitze von john/feature.

Git Collaboration 2

Merging

Git Collaboration 3

Rebasing

Dieses Rebasing verletzt die goldene Regel nicht (siehe Teil 2 dieser Artikelreihe), da nur unsere lokalen Feature-Commits bewegt werden – alles, was davor war, bleibt unberührt. Wir fügen unsere Änderungen quasi dem hinzu, was John bereits erledigt hat. In vielen Konstellationen ist das intuitiver als die Synchronisation mit dem Remote-Branch via Merge-Commit.

Per Voreinstellung führt git pull einen Merge aus, aber wir können die Integration des Remote-Branchs erzwingen, indem wir zusätzlich die Option --rebase nutzen.

Ein Feature via Pull-Request reviewen

Wenn wir im Code-Review-Prozess Pull-Requests nutzen, müssen wir git rebase nach dem Erstellen des Pull-Requests vermeiden. Sobald ein Pull-Request abgesetzt ist, sehen sich andere Entwickler unsere Commits an; es handelt sich nun also um einen öffentlichen Branch. Das Neuschreiben seiner Historie würde es Git und den anderen Teammitgliedern unmöglich machen, jedwede nachfolgenden Commits zu tracken, die dem Feature hinzugefügt werden.

Änderungen von anderen Entwicklern müssen mit git merge integriert werden. Aus diesem Grund ist es immer eine gute Idee, unseren Code mit einem interaktiven Rebase aufzuräumen, bevor wir einen Pull-Request erstellen.

Ein freigegebenes Feature integrieren

Nachdem ein Feature vom Team freigegeben wurde, besteht die Option, dieses Feature an die Spitze des master-Branchs zu rebasen, ehe wir git merge nutzen, um das Feature in die Haupt-Codebasis zu integrieren.

Das ist eine ähnliche Situation wie beim Integrieren von Upstream-Änderungen in den feature-Branch. Doch da wir keine Commits im master-Branch neu schreiben dürfen, müssen wir tatsächlich git merge nutzen, um das Feature zu integrieren. Indem wir vor dem Mergen allerdings ein Rebasing durchführen, stellen wir einen Fast-forward-Merge sicher und damit eine perfekt lineare Historie.

Git Collaboration 4

Initialer Status

Git Collaboration 5

Rebasing und Merging

Git Collaboration 6

Mergen ohne Rebasing

Wenn wir noch nicht ganz sicher im Umgang mit git rebase sind, können wir das Rebasing stets in einem temporären Branch durchführen. Auf diese Weise können wir, wenn wir die Historie des Features versehentlich verpfuscht haben, immer den Original-Branch auschecken und es erneut versuchen. Ein Beispiel:

git checkout feature
git checkout -b temporary-branch
git rebase -i master
# [Clean up the history]
git checkout master
git merge temporary-branch

Zusammenfassung

Das ist im Grunde alles, was wir wissen müssen, um mit dem Rebasing unserer Branches beginnen zu können. Wenn wir eine klare, lineare Historie bevorzugen, die frei von unnötigen Merge-Commits ist, ist git rebase in der Tat sehr hilfreich bei der Integration von Änderungen aus einem anderen Branch.

Wenn wir andererseits lieber die komplette Historie unseres Projekts behalten möchten und das Risiko vermeiden wollen, öffentliche Commits neu zu schreiben, können wir weiterhin auf git merge vertrauen. Auf jeden Fall wissen wir nun, was git rebase als Alternative leisten kann.

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