Historie mit Git Rebase umschreiben

Im grundlegenden Git-Workflow entwickeln Sie eine neue Funktion in einem dedizierten Themenzweig und führen sie anschließend wieder in einen Produktionszweig ein. Das macht git merge ein integrales Werkzeug zum Zusammenfügen von Zweigen. Es ist jedoch nicht das einzige, was Git anbietet.

Zweige kombinieren, indem sie zusammengefügt werden

Alternativ zu dem obigen Szenario können Sie die Zweige mit dem kombinieren Git Rebase Befehl. Anstatt die Zweige mit einem Merge-Commit zu verknüpfen, wird der gesamte Zweig des Features durch die Neubasis an die Spitze von verschoben Meister Wie nachfolgend dargestellt.

Zweige mit Git Rebase kombinieren

Dies dient dem gleichen Zweck wie git merge, Commits aus verschiedenen Branchen integrieren. Es gibt jedoch zwei Gründe, warum wir uns für eine Rebase gegen eine Verschmelzung entscheiden wollen:

  • Es ergibt sich eine lineare Projekthistorie.
  • Dies gibt uns die Möglichkeit, lokale Verpflichtungen zu bereinigen.

In diesem Lernprogramm werden diese zwei häufig verwendeten Anwendungsfälle von untersucht Git Rebase. Leider sind die Vorteile von Git Rebase komm zu einem Kompromiss. Bei falscher Verwendung kann dies eine der gefährlichsten Operationen sein, die Sie in einem Git-Repository ausführen können. Deshalb werden wir auch die Gefahren der Umbasierung genau unter die Lupe nehmen.

Voraussetzungen

In diesem Lernprogramm wird davon ausgegangen, dass Sie mit den grundlegenden Git-Befehlen und Collaboration-Workflows vertraut sind. Sie sollten mit der Erstellung und dem Festlegen von Snapshots vertraut sein, Features in isolierten Zweigen entwickeln, Zweige zusammenfügen und Zweige in entfernte Repositorys verschieben bzw. daraus ziehen.

1. Neuanpassung für eine lineare Historie

Der erste Anwendungsfall, den wir untersuchen wollen, beinhaltet eine abweichende Projekthistorie. Stellen Sie sich ein Repository vor, in dem Ihr Produktionszweig vorgerückt ist, während Sie eine Funktion entwickelt haben:

Um das zu widerlegen Merkmal verzweigen auf die Meister Verzweigung würden Sie die folgenden Befehle ausführen:

git Checkout-Funktion git rebase master

Dies transplantiert die Merkmal Verzweigung vom aktuellen Standort bis zur Spitze des Meister Ast:

Es gibt zwei Szenarien, in denen Sie dies tun möchten. Erstens, wenn sich das Feature auf die neuen Commits verlassen hat Meister, es hätte jetzt Zugang zu ihnen. Zweitens: Wenn das Feature abgeschlossen ist, wird es jetzt für eine schnelle Zusammenführung vorbereitet Meister. In beiden Fällen führt die Umbasierung zu einer linearen Historie, während git merge würde zu unnötigen Merge-Commits führen.

Überlegen Sie sich beispielsweise, was passieren würde, wenn Sie die Upstream-Commits mit einer Zusammenführung anstelle einer Rebase integrieren:

git Checkout-Funktion git merge master 

Dies hätte uns eine zusätzliche Zusammenführungsverpflichtung im Merkmal Ast. Außerdem würde dies jedes Mal passieren, wenn Sie Upstream-Commits in Ihre Funktion integrieren wollten. Letztendlich würde Ihr Projektverlauf mit bedeutungslosen Merge-Commits übersät sein.

Einbindung von Upstream-Commits mit einer Zusammenführung

Der gleiche Vorteil kann beim Zusammenfügen in die andere Richtung gesehen werden. Ohne eine Basis, die das fertige integriert Merkmal verzweigen in Meister erfordert ein Merge-Commit. Während dies tatsächlich eine sinnvolle Zusammenführungs-Commit ist (in dem Sinne, dass es ein abgeschlossenes Feature darstellt), ist der resultierende Verlauf voller Gabeln:

Ein abgeschlossenes Feature in eine Zusammenführung integrieren

Wenn Sie vor dem Zusammenfügen eine neue Basis festlegen, kann Git schnell vorspulen Meister zur Spitze von Merkmal. Sie finden eine lineare Geschichte über den Fortschritt Ihres Projekts in der Git Log Ausgabe-die Commits in Merkmal werden ordentlich auf den Commits in gruppiert Meister. Dies ist nicht notwendigerweise der Fall, wenn Zweige mit einem Merge-Commit verbunden sind.

Neuerstellung vor dem Zusammenführen

Konflikte lösen

Wenn du rennst Git Rebase, Git nimmt jedes Commit im Zweig und verschiebt es nacheinander auf die neue Basis. Wenn eines dieser Commits dieselbe Codezeile (n) wie das Upstream-Commit ändert, führt dies zu einem Konflikt.

Das git merge Mit dem Befehl können Sie alle Konflikte des Zweigs am Ende der Zusammenführung auflösen. Dies ist einer der Hauptzwecke einer Zusammenführungsfestlegung. Beim Umbasisieren funktioniert es jedoch etwas anders. Konflikte werden auf Commit-Basis gelöst. Also wenn Git Rebase Findet ein Konflikt, wird die Rebase-Prozedur angehalten und eine Warnmeldung angezeigt:

Readme.txt automatisch zusammenführen CONFLICT (Inhalt): Zusammenführen von Konflikten in readme.txt Fehler beim Zusammenführen der Änderungen ... Wenn Sie dieses Problem gelöst haben, führen Sie "git rebase --continue" aus. Wenn Sie diesen Patch lieber überspringen möchten, führen Sie stattdessen "git rebase --skip" aus. Führen Sie "git rebase --abort" aus, um den ursprünglichen Zweig zu überprüfen und die Umbasierung zu beenden.. 

Visuell sieht Ihr Projektverlauf dann so aus Git Rebase stößt auf einen Konflikt:

Die Konflikte können durch Ausführen überprüft werden Git-Status. Die Ausgabe sieht einem Zusammenführungskonflikt sehr ähnlich:

Nicht zusammengeführte Pfade: (Verwenden Sie "git reset HEAD") … "Um zu inszenieren" (verwenden Sie "git add") … "Um die Auflösung zu markieren) Beide wurden geändert: readme.txt - Änderungen wurden nicht hinzugefügt (verwenden Sie" git add "und / oder" git commit -a "). 

Um den Konflikt zu beheben, öffnen Sie die Konfliktdatei (readme.txt im obigen Beispiel), suchen Sie die betroffenen Zeilen und bearbeiten Sie sie manuell mit dem gewünschten Ergebnis. Teilen Sie Git dann mit, dass der Konflikt gelöst wird, indem Sie die Datei bereitstellen:

git add readme.txt 

Beachten Sie, dass dies die gleiche Art ist, wie Sie a markieren git merge Konflikt als gelöst. Denken Sie jedoch daran, dass Sie sich mitten in einer Rebase befinden - Sie möchten nicht den Rest der Commits vergessen, die verschoben werden müssen. Der letzte Schritt besteht darin, Git mitzuteilen, dass er die Umbasierung mit dem Befehl beendet --fortsetzen Möglichkeit:

Git Rebase - weiter 

Dadurch werden die restlichen Commits nach und nach verschoben. Wenn andere Konflikte auftreten, müssen Sie diesen Vorgang noch einmal wiederholen.

Wenn Sie den Konflikt nicht lösen möchten, können Sie sich für eines entscheiden --überspringen oder --abbrechen Flaggen. Letzteres ist besonders nützlich, wenn Sie keine Ahnung haben, was vor sich geht und Sie sich einfach wieder in Sicherheit bringen möchten.

# Ignorieren Sie das Commit, das den Konflikt verursacht hat. Git rebase --skip # Bricht die gesamte rebase ab und kehrt zum Zeichenbrett git rebase --abort zurück 

2. Neueinstellung zur Bereinigung lokaler Commits

Bisher haben wir nur verwendet Git Rebase Zweige verschieben, aber es ist viel mächtiger als das. Durch das Passieren der -ich kennzeichnen, können Sie eine interaktive Umbasissitzung beginnen. Durch interaktives Umbasieren können Sie genau festlegen, wie jedes Commit auf die neue Basis verschoben wird. Dadurch haben Sie die Möglichkeit, den Verlauf eines Features zu bereinigen, bevor Sie ihn mit anderen Entwicklern teilen.

Nehmen wir zum Beispiel an, Sie haben Ihre Arbeit beendet Merkmal Branch und Sie sind bereit, es zu integrieren Meister. Führen Sie den folgenden Befehl aus, um eine interaktive Umbasissitzung zu beginnen:

git Checkout-Funktion git rebase -i master 

Dadurch wird ein Editor geöffnet, der alle Commits in enthält Merkmal das sind zu bewegen:

pick 5c43c2b [Beschreibung für älteste Festschreibung] pick b8f3240 [Beschreibung für die zweitälteste Festschreibung] pick c069f4a [Beschreibung für letzte Festschreibung] 

Diese Auflistung definiert was Merkmal Branch wird aussehen wie nach der Rebase. Jede Zeile steht für ein Commit und das auswählen Der Befehl vor jedem Commit-Hash definiert, was während der Rebase damit passieren wird. Beachten Sie, dass die Commits vom ältesten bis zum neuesten aufgeführt sind. Durch das Ändern dieser Liste haben Sie die vollständige Kontrolle über Ihren Projektverlauf.

Wenn Sie die Reihenfolge der Commits ändern möchten, müssen Sie die Zeilen einfach neu anordnen. Wenn Sie die Nachricht eines Commits ändern möchten, verwenden Sie die umformulieren Befehl. Wenn Sie zwei Commits kombinieren möchten, ändern Sie das auswählen Befehl an quetschen. Dadurch werden alle Änderungen in diesem Commit in die darüber übertragen. Wenn Sie beispielsweise den zweiten Commit in der obigen Auflistung gestrichen haben, wird der Merkmal branch würde nach dem Speichern und Schließen des Editors wie folgt aussehen:

Das zweite Commit mit einer interaktiven Basis abmildern

Das bearbeiten Befehl ist besonders mächtig. Wenn das angegebene Commit erreicht ist, unterbricht Git die Rebase-Prozedur, ähnlich wie bei einem Konflikt. Dadurch haben Sie die Möglichkeit, den Inhalt des Commits mit zu ändern git begehen --amend oder sogar mehr Commits mit dem Standard hinzufügen git add/git begehen Befehle. Alle neuen Commits, die Sie hinzufügen, sind Teil des neuen Zweigs.

Interaktives Umbasieren kann tiefgreifende Auswirkungen auf Ihren Entwicklungsworkflow haben. Anstatt sich darum zu sorgen, dass Ihre Änderungen in eingekapselte Commits aufgeteilt werden, können Sie sich auf das Schreiben Ihres Codes konzentrieren. Wenn Sie am Ende eine einzige Änderung in vier separaten Snapshots festschrieben, dann ist dies kein Problem für das Umschreiben von Problemen Git Rebase -i und zerquetschen sie alle zu einem sinnvollen Commit.

3. Gefahren der Wiederbeschaffung

Nun haben Sie ein Verständnis von Git Rebase, wir können darüber reden, wenn wir es nicht benutzen. Intern werden bei der Umbasierung keine Commits in einen neuen Zweig verschoben. Stattdessen werden brandneue Commits erstellt, die die gewünschten Änderungen enthalten. In diesem Sinne wird die Umbasierung besser als das Folgende visualisiert:

Nach der Rebase macht sich das ein Merkmal wird unterschiedliche Festschreibungs-Hashes haben. Dies bedeutet, dass wir nicht nur einen Zweig neu positionieren. Wir haben unsere Projekthistorie buchstäblich umgeschrieben. Dies ist ein sehr wichtiger Nebeneffekt von Git Rebase.

Wenn Sie alleine an einem Projekt arbeiten, ist das Umschreiben der Historie keine große Sache. Sobald Sie jedoch in einer kollaborativen Umgebung arbeiten, kann dies sehr gefährlich werden. Wenn Sie Commits neu schreiben, die von anderen Entwicklern verwendet werden (z. B. Commits für Meister Branch), wird es so aussehen, als ob diese Commits beim nächsten Versuch verschwunden wären. Dies führt zu einem verwirrenden Szenario, das sich nur schwer wiederherstellen lässt.

Aus diesem Grund sollten Sie Commits, die an ein öffentliches Repository weitergeleitet wurden, niemals widerlegen, es sei denn, Sie sind sich sicher, dass niemand ihre Arbeit darauf basiert.

Fazit

In diesem Tutorial wurden die beiden häufigsten Anwendungsfälle von vorgestellt Git Rebase. Wir haben viel über das Verschieben von Zweigen geredet, bedenken Sie jedoch, dass es bei der Umbasierung wirklich um die Kontrolle Ihres Projektverlaufs geht. Die Möglichkeit, Commits nach der Tatsache umzuschreiben, gibt Ihnen die Freiheit, sich auf Ihre Entwicklungsaufgaben zu konzentrieren, anstatt Ihre Arbeit in isolierte Momentaufnahmen aufzuteilen.

Beachten Sie, dass das Umbasieren eine völlig optionale Ergänzung Ihrer Git-Toolbox ist. Sie können immer noch alles, was Sie brauchen, mit einfachem Altem git merge Befehle. Dies ist in der Tat sicherer, da dadurch die Möglichkeit vermieden wird, die öffentliche Geschichte umzuschreiben. Wenn Sie jedoch die Risiken verstehen, Git Rebase kann eine viel sauberere Methode sein, um Zweige im Vergleich zum Zusammenführen von Commits zu integrieren.