Git Guide Teil Nummer 2: Die goldene Regel und andere Grundlagen der Rebase

Mal sehen, was passiert, wenn Sie Git Rebase ausführen und warum Sie vorsichtig sein müssen. 

Dies ist der zweite und dritte Teil des Git-Leitfadens aus dem Blog von Pierre de Wulf, der vom Mail.ru Cloud Solutions- Team übersetzt wurde . Der erste Teil kann hier gelesen werden .

Die Essenz der Rebase


Wie genau geschieht Rebase:


Sie können sagen, dass Rebase darin besteht, den Zweig, den Sie verschieben möchten, zu lösen und mit einem anderen Zweig zu verbinden. Diese Definition ist wahr, aber versuchen Sie, etwas tiefer zu schauen. Wenn Sie sich die Dokumentation ansehen , steht Folgendes über Rebase: "Commits auf einen anderen Zweig anwenden (Commits erneut auf einen anderen Basistipp anwenden)".

Das Hauptwort hier ist anzuwenden, da Rebase nicht nur das Kopieren und Einfügen von Zweigen in einen anderen Zweig ist. Rebase übernimmt nacheinander alle Commits aus dem ausgewählten Zweig und wendet sie erneut auf den neuen Zweig an.

Dieses Verhalten führt zu zwei Punkten:

  1. Durch erneutes Anwenden von Commits erstellt Git neue Commits. Selbst wenn sie dieselben Änderungen enthalten, wird Git als neues und unabhängiges Commit betrachtet.
  2. Git Rebase überschreibt Commits und löscht keine alten. Dies bedeutet, dass Ihre alten Commits nach Abschluss der Rebase weiterhin im Unterordner / gjects des Ordners .git gespeichert werden. Wenn Sie nicht vollständig verstehen, wie Git Commits speichert und berücksichtigt, lesen Sie den ersten Teil dieses Artikels.

Hier ist eine korrektere Interpretation dessen, was während der Rebase passiert:


Wie Sie sehen, enthält der Feature-Zweig völlig neue Commits. Wie bereits erwähnt, die gleichen Änderungen, aber aus Sicht von Git völlig neue Objekte. 

Dies bedeutet auch, dass alte Commits nicht zerstört werden. Sie werden einfach direkt unzugänglich. Wenn Sie sich erinnern, ist ein Zweig nur ein Link zu einem Commit. Wenn also weder ein Zweig noch ein Tag auf ein Commit verweisen, kann nicht mit Git darauf zugegriffen werden, obwohl es weiterhin auf der Festplatte vorhanden ist.

Lassen Sie uns nun die Goldene Regel diskutieren.

Goldene Rebase-Regel


Die goldene Rebase-Regel lautet: NIEMALS einen gemeinsam genutzten Zweig neu gründen! ". Ein gemeinsam genutzter Zweig bezieht sich auf einen Zweig, der im Netzwerk-Repository vorhanden ist und mit dem andere Personen außer Ihnen arbeiten können.

Oft wird diese Regel ohne angemessenes Verständnis angewendet, daher werden wir analysieren, warum sie aufgetreten ist, zumal sie dazu beiträgt, die Arbeit von Git besser zu verstehen.

Schauen wir uns eine Situation an, in der ein Entwickler gegen die goldene Regel verstößt, und was in diesem Fall passiert.

Angenommen, Bob und Anna arbeiten zusammen an einem Projekt. Im Folgenden sehen Sie, wie die Bob- und Anna-Repositorys und das ursprüngliche Repository auf GitHub aussehen:


Alle Benutzer haben Repositorys mit GitHub synchronisiert.

Jetzt führt Bob, der gegen die goldene Regel verstößt, eine Rebase durch, und gleichzeitig erstellt Anna, die im Feature-Zweig arbeitet, ein neues Commit:


Sehen Sie, was passieren wird?

Bob versucht, ein Push-Commit auszuführen, und er bekommt eine Ablehnung von so etwas:


Git war nicht erfolgreich, da Git nicht wusste, wie man den Feature-Zweig von Bob mit dem Feature-Zweig von GitHub kombiniert.

Die einzige Lösung, die es Bob ermöglicht, zu pushen, ist die Verwendung der Force-Taste, die das GitHub-Repository anweist, den Feature-Zweig zu entfernen und den zu akzeptieren, den Bob für diesen Zweig drückt. Danach bekommen wir folgende Situation:


Jetzt möchte Anna ihre Änderungen starten, und hier ist, was passieren wird:


Dies ist normal, sagte Git zu Anna, dass sie keine synchronisierte Version des Feature-Zweigs hat, dh ihre Version des Zweigs und die Version des Zweigs in GitHub sind unterschiedlich. Anna muss den Zug abschließen. Auf die gleiche Weise, wie Git beim Push einen lokalen Zweig mit einem Zweig im Repository zusammenführt, versucht Git beim Ziehen, den Zweig im Repository mit einem lokalen Zweig zusammenzuführen.

Bevor Sie Pull-Commits in den lokalen und GitHub-Zweigen ausführen, sehen Sie folgendermaßen aus:

A--B--C--D'   origin/feature // GitHub
A--B--D--E    feature        // Anna

Beim Ziehen wird Git zusammengeführt, um den Unterschied in den Repositorys zu beseitigen. Und wozu führt das:


Commit M ist ein Merge-Commit. Schließlich werden die Feature-Zweige von Anna und GitHub vollständig zusammengeführt. Anna atmete erleichtert auf, alle Konflikte waren gelöst, sie kann einen Stoß ausführen. 

Bob zieht, jetzt ist alles synchron:


Wenn man sich das daraus resultierende Durcheinander ansieht, muss man sicherstellen, dass die goldene Regel wichtig ist. Denken Sie auch daran, dass ein solches Durcheinander nur von einem Entwickler und in einem Zweig erstellt wurde, der von nur zwei Personen gemeinsam genutzt wird. Stellen Sie sich vor, Sie sind in einem Team von zehn Personen. 

Einer der vielen Vorteile von Git ist, dass Sie jederzeit problemlos zurücksetzen können. Aber je mehr Fehler gemacht werden, wie beschrieben, desto schwieriger ist es, dies zu tun.

Beachten Sie auch, dass doppelte Commits im Netzwerk-Repository angezeigt werden. In unserem Fall D und D ', die dieselben Daten enthalten. Tatsächlich kann die Anzahl der doppelten Commits so groß sein wie die Anzahl der Commits in Ihrem neu basierten Zweig.

Wenn Sie immer noch nicht überzeugt sind, stellen wir Emma vor, die dritte Entwicklerin. Sie arbeitet in der Feature-Branche, bevor Bob seinen Fehler macht und derzeit pushen will. Angenommen, zu dem Zeitpunkt, als sie pusht, ist unser kleines vorheriges Skript bereits fertig. Folgendes kommt heraus:


Oh, dieser Bob !!!!

Dieser Text könnte Sie denken lassen, dass Rebase nur verwendet wird, um einen Zweig an den Anfang eines anderen Zweigs zu verschieben. Dies ist optional - Sie können auf demselben Zweig neu basieren.

Beauty Pull Rebase


Wie Sie oben gesehen haben, hätten Annas Probleme vermieden werden können, wenn sie Pull Rebase verwendet hätte. Lassen Sie uns diese Frage genauer betrachten.

Nehmen wir an, Bob arbeitet in einem Zweig, der vom Meister abweicht, dann könnte seine Geschichte so aussehen:




Bob beschließt, dass es Zeit ist zu ziehen, was, wie Sie bereits verstanden haben, zu Verwirrung führen wird. Da sich Bobs Repository von GitHub entfernt hat, fragt Git, ob die Zusammenführung abgeschlossen ist, und das Ergebnis sieht folgendermaßen aus:


Diese Lösung funktioniert und funktioniert einwandfrei. Es kann jedoch hilfreich sein, zu wissen, dass es andere Lösungen für das Problem gibt. Eine davon ist Pull-Rebase.

Wenn Sie Pull-Rebase ausführen, versucht Git herauszufinden, welche Commits sich nur in Ihrem Zweig und welche im Netzwerk-Repository befinden. Git kombiniert dann die Commits aus dem Netzwerk-Repository mit dem neuesten Commit, das sowohl im lokalen als auch im Netzwerk-Repository vorhanden ist. Stellen Sie dann Ihre lokalen Commits auf das Ende der Verzweigung zurück. 

Es klingt kompliziert, also veranschaulichen wir:

  1. Git achtet nur auf die Commits, die sich sowohl in Ihrem als auch im Netzwerk-Repository befinden:

    Es sieht aus wie ein lokaler Klon des GitHub-Repositorys.
  2. Git Rebase lokale Commits:


Wie Sie sich erinnern, wendet Git beim Festschreiben von Commits nacheinander Commits an, dh in diesem Fall wendet Master Commit E und dann F. bis zum Ende des Zweigs an. Das Ergebnis ist Rebase für sich. Es sieht gut aus, aber die Frage stellt sich - warum das?

Meiner Meinung nach besteht das größte Problem beim Zusammenführen von Zweigen darin, dass die Geschichte der Commits verschmutzt ist. Daher ist Pull-Rebase eine elegantere Lösung. Ich würde sogar noch weiter gehen und sagen, dass Sie immer Pull-Rebase verwenden sollten, wenn Sie die neuesten Änderungen in Ihre Filiale herunterladen müssen. Beachten Sie jedoch Folgendes: Da bei der erneuten Basis alle Commits der Reihe nach angewendet werden, müssen Sie bei der erneuten Basis für 20 Commits möglicherweise 20 Konflikte nacheinander lösen. 

In der Regel können Sie den folgenden Ansatz verwenden: Eine große Änderung, die vor langer Zeit vorgenommen wurde, ist das Zusammenführen, zwei kleine Änderungen, die kürzlich als Pull-Rebase vorgenommen wurden.

Stärke Rebase auf


Angenommen, Ihr Commit-Verlauf sieht folgendermaßen aus:




Sie möchten also den Zweig von Feature 2 auf den Hauptzweig umstellen. Wenn Sie eine regelmäßige Rebase für den Hauptzweig durchführen, erhalten Sie Folgendes:


Es ist unlogisch, dass Commit D in beiden Zweigen vorhanden ist: in Feature 1 und Feature 2. Wenn Sie den Zweig von Feature 1 an das Ende des Hauptzweigs verschieben, wird Commit D zweimal angewendet.

Angenommen, Sie müssen ein anderes Ergebnis erzielen:


Um ein solches Szenario zu implementieren, ist Git Rebase genau das, was beabsichtigt ist.

Lesen Sie zuerst die Dokumentation:

SYNOPSIS
       git rebase [-i | --interactive] [<options>] [--exec <cmd>]
               [--onto <newbase> | --keep-base] [<upstream> [<branch>]]
       git rebase [-i | --interactive] [<options>] [--exec <cmd>] 
[--onto <newbase>]
               --root [<branch>]
       git rebase (--continue | --skip | --abort | --quit | --edit-todo 
| --show-current-patch)


Das interessiert uns:

OPTIONS
       --onto <newbase>
          Starting point at which to create the new commits. If the 
--onto option is not specified, the starting point is <upstream>. May be 
any valid commit, and not just an existing branch name.


Verwenden Sie diese Option, um anzugeben, an welchem ​​Punkt neue Commits erstellt werden sollen.

Wenn diese Option nicht angegeben ist, wird der Upstream zum Ausgangspunkt.

Zum Verständnis werde ich noch ein Bild geben:

A--B--C        master
    \
     D--E      feature1
         \
          F--G feature2

Here we want to rebase feature2 to master beginning from feature1
                           |                                |
                        newbase                         upstream


Das heißt, der Hauptzweig ist newbase und der Zweig für Merkmal 1 ist vorgelagert.

Wenn Sie also das Ergebnis wie in der letzten Abbildung erhalten möchten, müssen Sie git rebase --onto master feature1 im Zweig feature2 ausführen.

Viel Glück

Übersetzt mit Unterstützung von Mail.ru Cloud Solutions .

Was gibt es sonst noch zu diesem Thema zu lesen :

  1. Der erste Teil des Git-Handbuchs.
  2. Mein zweites Jahr als unabhängiger Entwickler .
  3. Unser Telegrammkanal zur digitalen Transformation


All Articles