Kapitel 8 · Übung
Lokal zusammenarbeiten
Einen Branch auf den neuesten Stand bringen
Zwei Menschen können beim selben Commit anfangen und dann unterschiedliche Commits erstellen. Git nennt das Ergebnis Divergenz: Keiner der beiden Branches enthält alles vom anderen. Keine Arbeit ist dadurch automatisch falsch oder verloren. Die Verläufe müssen nur zusammengeführt werden, bevor der gemeinsame Branch vorankommen kann.
Die drei Repositories kennenlernen
Dieses Kapitel bleibt vollständig innerhalb einer Übungsumgebung:
/workspace/
├── shop/ your working repository
├── origin.git/ the bare repository used to exchange history
└── colleague/ an observation clone that must remain unchanged
Das vorbereitete Repository shop steht bereits auf main, und sein Arbeitsbaum ist sauber. Sein lokaler main enthält zwei Commits zur Belegausgabe. Seine Remote-Tracking-Referenz origin/main verzeichnet zwei Commits zur Mengenverarbeitung, die über colleague kamen. Beide Linien beginnen beim selben früheren Commit.
Beginne mit Befehlen, die du bereits kennst:
pwd
git status
Der Statusbericht sagt, dass main und origin/main auseinandergelaufen sind, und zeigt eine ahead/behind-Zählung. „Ahead by 2“ bedeutet, dass der lokale main zwei Commits erreicht, die origin/main nicht erreicht. „Behind by 2“ bedeutet, dass origin/main zwei Commits erreicht, die der lokale main nicht erreicht. Die Zahlen beschreiben Erreichbarkeit zwischen Commit-Verläufen, keine Bewertung und keine Anzahl geänderter Dateien.
Das Wissen dieses Repositorys auffrischen
Der Befehl git fetch kontaktiert das gespeicherte Repository origin, lädt hier fehlende Commits und Referenzen herunter und aktualisiert Remote-Tracking-Referenzen wie origin/main. Er verschiebt den lokalen main nicht und verändert den Arbeitsbaum nicht. Führe ihn vor einer Entscheidung zur Zusammenarbeit aus, damit du mit den neuesten Informationen arbeitest, die dieses Repository bekommen kann:
git fetch
git status
In dieser fest vorbereiteten Umgebung war origin/main bereits aktuell. Die ahead/behind-Zahlen bleiben deshalb bei zwei und zwei. Auch dieses unveränderte Ergebnis ist ein nützlicher Beleg: Du hast geprüft statt geraten.
Beide Seiten der Aufteilung vergleichen
Mit einem Verlaufsbereich kann git log Commits anzeigen, die von einem Namen aus erreichbar sind, von einem anderen aber nicht. In A..B bezeichnet der rechte Name die Seite, die Git zeigt. Commits, die auch vom linken Namen aus erreichbar sind, werden ausgeschlossen. Die Option --oneline stellt jeden passenden Commit mit einer abgekürzten Kennung und seiner Betreffzeile dar. So lassen sich die beiden kurzen Listen leichter vergleichen. Der erste folgende Befehl zeigt deshalb die Commits der Kollegenseite, die dem lokalen main fehlen. Der zweite dreht den Bereich um und zeigt die lokalen Commits, die origin/main fehlen:
git log --oneline main..origin/main
git log --oneline origin/main..main
Lies die Betreffzeilen vor dem Zusammenführen. Die Kollegenseite ergänzt die Mengenverarbeitung und dokumentiert sie. Deine Seite ergänzt die Belegausgabe und einen Test. Die Änderungen sind unterschiedlich, aber miteinander vereinbar. Beide gehören deshalb ins Ergebnis.
Warum der erste Push stoppen muss
git push bittet das Bare-Repository origin, seinen Branch main auf deinen lokalen main zu verschieben. Derzeit würden dadurch die beiden Kollegen-Commits aus seinem Verlauf fallen, die nur origin erreicht. Git weist diesen Non-Fast-Forward-Push zurück, weil der gewünschte neue letzte Commit den aktuellen letzten Commit des Remotes nicht enthält. Führe den gewöhnlichen Befehl aus und lies die Ablehnung:
git push
Die Ablehnung schützt Arbeit. Sie ist keine Aufforderung, den Push zu erzwingen. Der Weg weiter hat drei Schritte: das Wissen über das Remote auffrischen, die Remote-Tracking-Referenz in den lokalen Branch integrieren und dann das zusammengeführte Ergebnis pushen. Du hast bereits abgerufen und beide Seiten geprüft. Als Nächstes kommt deshalb das Zusammenführen.
Zusammenführen, ohne eine Seite zu verlieren
Du hast git merge in Kapitel 6 kennengelernt. Hier bedeutet git merge origin/main: „Nimm den Commit-Verlauf, den meine Remote-Tracking-Referenz bezeichnet, in meinen aktuellen Branch auf.“ Weil beide Seiten eigene Commits haben, erstellt Git einen Merge-Commit mit zwei Vorgängern. Die Option -m gibt seine Nachricht direkt an, sodass kein Editor geöffnet werden muss. Der Ausgangszustand ist so vorbereitet, dass dieser Merge ohne Konflikt durchläuft:
git merge origin/main -m "Merge origin main"
git status
Nach dem Merge meldet git status einen sauberen Arbeitsbaum und sagt, dass der lokale main vor origin/main liegt. Das ist erwartbar: Der zusammengeführte Commit existiert nur in shop, bis die nächste Lektion ihn pusht.
Ein ehrliches Wort zu rebase
Du wirst hören, dass git rebase ein anderer Weg ist, das gerade Erledigte zu tun. Das stimmt. Ein Merge bewahrt beide Linien genau so, wie sie entstanden sind, und fügt einen Commit hinzu, der ihren Treffpunkt festhält. Ein Rebase kopiert deine Commits stattdessen ans Ende der anderen Linie. So entsteht eine geradlinigere Geschichte, und deine Commits erhalten neue Kennungen.
Keine der beiden Möglichkeiten ist die eine richtige Antwort. Teams wählen eine Gewohnheit, vor allem danach, ob das Umschreiben ihrer eigenen Commits sicher ist und was sie miteinander vereinbart haben. Dieser Kurs übt Merge, weil es niemals einen Commit umschreibt, den ein Kollege bereits besitzen könnte, und weil die Verbindung danach sichtbar bleibt. Wenn du in ein Team kommst, das Rebase verwendet, ist alles vor dem Integrationsschritt identisch: abrufen und beide Seiten lesen.
Dein erstes git push wurde abgelehnt. Was hat Git geschützt?
git status sagte, dass main um 2 Commits voraus und um 2 zurückliegt. Was beschreibt das?
Beide Entwicklungslinien liegen jetzt in einem Verlauf, und der Merge-Commit hält ihren Treffpunkt fest. Niemandes Arbeit wurde der Arbeit einer anderen Person vorgezogen. Genau dieses Ergebnis ist erstrebenswert, wenn die andere Linie jemand anderem gehört und nicht dir selbst.
Dein Repository ist dem gemeinsamen jetzt voraus. Diese Lücke schließt die nächste Lektion. Diesmal wird der Push angenommen.