Einführung in Git (Teil 3): Kollaboratives Arbeiten

Einführung in Git (Teil 3): Kollaboratives Arbeiten

In meinem letzten Artikel hatte ich bereits erläutert, wie ihr in Git mit verschiedenen Zweigen arbeiten könnt. Häufig ist es jedoch so, dass ihr nicht alleine an einem Projekt arbeitet, sondern eure Änderungen mit anderen Entwicklern koordinieren müsst. Ein Extrem-Beispiel hierfür ist das Git-Repository des Linux-Kernels: dieses enthält Commits von 2.864 verschiedenen Entwicklern (allein 2013!). In diesem Artikel möchte ich daher auf das kollaborative Arbeiten mit Git eingehen.

  1. Repositories von anderen Entwicklern klonen
  2. Remote-Repositories und externe Zweige
  3. Push und Pull
  4. Arbeiten mit zentralen Git-Repositories
  5. Ausblick
    1. Bisherige Beiträge der Git-Reihe:

Repositories von anderen Entwicklern klonen

In den bisherigen Beispielen bin ich stets davon ausgegangen, dass ihr mit einem Repository gearbeitet habt, das ihr selbst erstellt habt. Häufig ist es jedoch so, dass bereits irgendwo ein Repository mit Versionsgeschichte existiert, welches ihr übernehmen möchtet. Hierzu dient der Befehl git clone.

Für unser Beispiel nehmen wir an, dass wir zwei Entwickler haben, die untereinander Code austauschen möchten: Alice und Bob. Angenommen, Alice hat bereits ein existierendes Repository, welches sie mit Bob teilen möchte, dann kann Bob das Repository nun von Alice klonen:

Voraussetzung hierzu ist, dass Bob SSH-Zugriff auf den Rechner von Alice hat. Alternativ könnte Alice auf ihrem Rechner auch einen Git-Server installieren, der einen Zugriff über HTTP oder ein Git-eigenes Protokoll erlaubt.

Der Befehl git clone lädt das gesamte Repository einschließlich der gesamten Versionsgeschichte (also aller Commits) auf den lokalen Rechner herunter. Dies ist ein wichtiger Unterschied zu zentralen Versionsverwaltungssystemen wie beispielsweise Subversion, die lediglich den jeweils aktuellen Versionsstand lokal vorhalten und die gesamte Versionsgeschichte auf dem Server belassen. Innerhalb des geklonten Repositories kann Bob nun genau so arbeiten, wie wir es in den bisherigen Beispielen auch mit selbst initialisierten Repositories betrachtet hatten.

Remote-Repositories und externe Zweige

Jedes Git-Repository kann Referenzen zu beliebig vielen anderen externen Repositories enthalten, den Remotes. Wird ein bestehendes Repository geklont, trägt Git automatisch den URI des Original-Repositories als ein Remote mit dem Namen origin ein. Bob kann sich in seinem geklonten Repository die Liste der Remotes nun mit dem Befehl git remote ausgeben lassen (mit dem Parameter -v gibt Git auch die URIs aus):

Mit dem Befehl git remote können auch Namen und URIs von Remote-Repositories geändert werden. Möchte Bob das Remote also von origin in alice umbenennen, ginge das wie folgt:

Für jeden Zweig, der in einem Remote existiert, verwaltet Git einen sogenannten externen Zweig. Diese sind stets nach dem Schema <Repository>/<Zweig> benannt. Existiert in Alices Repository also ein master-Zweig, so würde Bob diesen Zweig nach dem Klonen zunächst unter dem Namen origin/master sehen (bzw. nach dem Umbenennen des Remotes als alice/master). Nichtsdestotrotz hat Bob aber auch einen eigenen master-Zweig (der nach dem Klonen jedoch auf denselben Commit zeigt wie Alices master-Zweig):

Externe Zweige bilden lediglich den Zustand des entfernten Repositories ab; sie können nicht ausgecheckt oder lokal verändert werden. Abgesehen davon verhalten sich externe Zweige jedoch genau so, wie von Git-Zweigen bereits gewohnt.

Was passiert nun, wenn Alice an ihrem Projekt weiterarbeitet, und neue Commits hinzufügt? Da Git-Repositories prinzipiell rein lokal vorliegen, bekommt Bob von Alices Änderungen zunächst einmal überhaupt nichts mit. Bob kann mit dem Befehl git fetch <remote> jedoch neue Commits herunterladen, die seit dem Klonen hinzugekommen sind:

Der Befehl git fetch lädt neue Commits von einem Remote-Repository herunter und aktualisiert die externen Zweige. Er verändert jedoch nicht den HEAD-Zeiger; dies bedeutet, dass der lokale Working-Tree des Repositories zunächst nicht beeinflusst wird:

Im obigen Beispiel hat Alice nun zwei neue Commits erstellt, nachdem Bob das Repository geklont hat. Durch den Befehl git fetch wurden diese Commits heruntergeladen und der externe Zweig alice/master wurde entsprechend verschoben.

Wie ihr im Beispiel sehen könnt, zeigt Bobs HEAD bzw. der master-Zweig immer noch auf den alten Commit C. Um die neu hinzugekommenen Commits nun in Bobs master-Zweig zu übernehmen, reicht das altbekannte git merge:

Da es in diesem Fall zu keiner echten Verzweigung gekommen ist, führt Git einen einfachen Fastforward-Merge aus:

Was wäre passiert, wenn Bob bereits eigene Commits im master-Zweig erstellt hätte? In diesem Fall hätte Git keinen Fastforward-, sondern einen Dreiwege-Merge durchgeführt; ansonsten wäre jedoch alles gleich geblieben:

Alternativ dazu hätte Bob auch einen Rebase durchführen können:

Push und Pull

Falls euch die Kombination aus git fetch und git merge zu umständlich ist, könnt ihr als Kurzform auch das Kommando git pull verwenden:

git pull lädt den zu dem jeweiligen ausgecheckten Zweig (den, auf den der HEAD-Pointer zeigt) gehörigen externen Zweig herunter (den sogenannten Tracking Branch) und führt diesen mit dem aktuellen HEAD zusammen (prinzipiell also genau das, was wir oben mit git fetch und git merge bereits gemacht haben).

Alternativ kann git pull per Parameter auch dazu gebracht werden, statt eines Merges einen Rebase durchzuführen:

Doch was ist, wenn nun umgekehrt Alice die Änderungen von Bob übernehmen möchte? Zunächst einmal kann Alice das Repository von Bob als Remote-Repository hinzufügen:

Der Parameter -f sorgt dafür, dass implizit gleich ein git fetch ausgefüht wird und somit alle Zweige des neuen Remote-Repositories hinzugefügt werden. Im nächsten Schritt kann Alice nun Bobs master-Zweig mit ihrem eigenen zusammenführen:

In diesem Fall ist Bob also darauf angewiesen, dass Alice sich seine Änderungen herunterlädt (pullt). Alternativ kann Bob mit dem Befehl git push seine Änderungen auch an Alice übertragen:

Wichtig beim Push ist in diesem Fall, dass Bob einen alternativen Zweig-Namen angibt (in diesem Fall bob/master statt einfach nur master). Andernfalls würde Git versuchen, Alices master-Zweig auf den neuen Commit zu verschieben. Dies würde jedoch in einer Fehlermeldung enden, wenn Alice diesen Zweig gerade ausgecheckt hat. Gibt Bob einen alternativen Zweig-Namen an, würde ein neuer Zweig in Alices Repository angelegt. Diesen könnte sie dann wie gehabt in ihren eigenen master-Zweig mergen.

Arbeiten mit zentralen Git-Repositories

Das dezentrale Arbeiten wie gerade beschrieben ist eines der Alleinstellungsmerkmale von Git. Häufig macht es aus organisatorischen Gründen jedoch Sinn, dennoch ein zentrales (und authoritatives) Repository einzurichten, an das alle Entwickler ihre Änderungen pushen können. In diesem Fall ist es jedoch ungünstig, wenn jeder Entwickler seine Änderungen in einen eigenen Zweig im Remote-Repository pushen würde (denn irgendwer müsste diese Zweige am Ende ja alle wieder zusammenführen).

Um das Problem zu umgehen, können spezielle Repositories erstellt werden, die keinen Working Tree haben (sogenannte Bare-Repositories). Dies ist über einen entsprechenden Parameter bei git init möglich:

In dieses zentrale Repository können nun alle Entwickler ohne Einschränkungen pushen:

Alice könnte nun wiederum Änderungen aus diesem Repository pullen:

Ausblick

Beim Arbeiten mit zentralen Repositories ist es häufig nicht sinnvoll, allen Anwendern vollen SSH-Zugriff auf den Server zu geben. Hier kommen spezielle Git-Server ins Spiel, die beispielsweise auch einen Push über HTTP ermöglichen und Zusatzfeatures wie etwa Zugriffskontrolle anbieten. In einem weiteren Blog-Artikel werde ich darum später noch einmal auf spezielle Server-Software für Git eingehen.

Bisherige Beiträge der Git-Reihe:

Einführung in Git (Teil 1): Versionsverwaltung

Einführung in Git (Teil 2): Branching und Merging

Kommentare

  1. Dennis Laudenbach am

    Tolle Beiträge zum Thema GIT…allerdings etwas allgemein gehalten.
    Wie richte ich es nun als Newbie ein, dass ich meinen lokalen Entwicklungsstand in einen Mittwald Account bekomme?

    Antworten

Kommentar hinzufügen

    Hilfe & Kontakt

    Support-Hotline
    +49 (0) 800/440-3000

    E-Mail
    support@mittwald.de