Kapitel ▾ 2. Auflage

3.5 Git Branching - Remote-Branches

Remote-Branches

Remote-Referenzen sind Referenzen (Zeiger) in Ihren Remote-Repositories, einschließlich Branches, Tags und so weiter. Sie können eine vollständige Liste der Remote-Referenzen explizit mit git ls-remote <remote> oder für Remote-Branches mit git remote show <remote> sowie weitere Informationen abrufen. Eine gängigere Methode ist jedoch, Remote-Tracking-Branches zu nutzen.

Remote-Tracking-Branches sind Referenzen auf den Zustand von Remote-Branches. Es sind lokale Referenzen, die Sie nicht verschieben können; Git verschiebt sie für Sie, wann immer Sie eine Netzwerkkommunikation durchführen, um sicherzustellen, dass sie den Zustand des Remote-Repositories genau wiedergeben. Betrachten Sie sie als Lesezeichen, die Sie daran erinnern, wo sich die Branches in Ihren Remote-Repositories befanden, als Sie das letzte Mal eine Verbindung zu ihnen hergestellt haben.

Namen von Remote-Tracking-Branches haben die Form <remote>/<branch>. Wenn Sie beispielsweise sehen möchten, wie der master-Branch auf Ihrem origin-Remote zum Zeitpunkt der letzten Kommunikation mit ihm aussah, würden Sie den origin/master-Branch überprüfen. Wenn Sie an einem Problem mit einem Partner arbeiteten und er einen iss53-Branch hochgeladen hat, haben Sie vielleicht Ihren eigenen lokalen iss53-Branch, aber der Branch auf dem Server wird durch den Remote-Tracking-Branch origin/iss53 repräsentiert.

Dies mag etwas verwirrend sein, lassen Sie uns also ein Beispiel betrachten. Angenommen, Sie haben einen Git-Server in Ihrem Netzwerk unter git.ourcompany.com. Wenn Sie von diesem klonen, benennt der clone-Befehl von Git ihn automatisch origin für Sie, lädt alle seine Daten herunter, erstellt einen Zeiger auf den master-Branch und nennt ihn lokal origin/master. Git gibt Ihnen auch Ihren eigenen lokalen master-Branch, der an derselben Stelle beginnt wie der master-Branch von origin, damit Sie etwas zum Arbeiten haben.

Hinweis
„origin“ ist nichts Besonderes

So wie der Branch-Name „master“ keine besondere Bedeutung in Git hat, hat auch „origin“ keine. Während „master“ der Standardname für einen Start-Branch ist, wenn Sie git init ausführen, was der einzige Grund ist, warum er weit verbreitet ist, ist „origin“ der Standardname für ein Remote, wenn Sie git clone ausführen. Wenn Sie stattdessen git clone -o booyah ausführen, haben Sie booyah/master als Ihren Standard-Remote-Branch.

Server and local repositories after cloning
Abbildung 30. Server- und lokale Repositories nach dem Klonen

Wenn Sie einige Arbeiten an Ihrem lokalen master-Branch durchführen und in der Zwischenzeit jemand anderes auf git.ourcompany.com pusht und dessen master-Branch aktualisiert, dann entwickeln sich Ihre Historien unterschiedlich weiter. Solange Sie keinen Kontakt mit Ihrem origin-Server haben, bewegt sich Ihr origin/master-Zeiger nicht.

Local and remote work can diverge
Abbildung 31. Lokale und Remote-Arbeiten können abweichen

Um Ihre Arbeit mit einem bestimmten Remote zu synchronisieren, führen Sie den Befehl git fetch <remote> aus (in unserem Fall git fetch origin). Dieser Befehl sucht, welcher Server „origin“ ist (in diesem Fall ist es git.ourcompany.com), holt alle Daten von ihm, die Sie noch nicht haben, und aktualisiert Ihre lokale Datenbank, indem er Ihren origin/master-Zeiger an seine neue, aktuellere Position verschiebt.

`git fetch` updates your remote-tracking branches
Abbildung 32. git fetch aktualisiert Ihre Remote-Tracking-Branches

Um zu demonstrieren, wie mehrere Remote-Server und Remote-Branches für diese Remote-Projekte aussehen, nehmen wir an, Sie haben einen weiteren internen Git-Server, der nur für die Entwicklung durch eines Ihrer Sprint-Teams verwendet wird. Dieser Server ist unter git.team1.ourcompany.com erreichbar. Sie können ihn als neue Remote-Referenz zu dem Projekt hinzufügen, an dem Sie gerade arbeiten, indem Sie den Befehl git remote add ausführen, den wir in Git Basics behandelt haben. Benennen Sie dieses Remote teamone, was Ihr Kurzname für diese gesamte URL sein wird.

Adding another server as a remote
Abbildung 33. Hinzufügen eines weiteren Servers als Remote

Jetzt können Sie git fetch teamone ausführen, um alles abzurufen, was der Remote teamone-Server hat, was Sie noch nicht haben. Da dieser Server derzeit eine Untermenge der Daten Ihres origin-Servers enthält, ruft Git keine Daten ab, setzt aber einen Remote-Tracking-Branch namens teamone/master, der auf den Commit zeigt, den teamone als seinen master-Branch hat.

Remote-tracking branch for `teamone/master`
Abbildung 34. Remote-Tracking-Branch für teamone/master

Pushen

Wenn Sie einen Branch mit der Welt teilen möchten, müssen Sie ihn auf ein Remote pushen, auf das Sie Schreibzugriff haben. Ihre lokalen Branches werden nicht automatisch mit den Remotes synchronisiert, auf die Sie schreiben – Sie müssen die Branches, die Sie teilen möchten, explizit pushen. Auf diese Weise können Sie private Branches für Arbeiten verwenden, die Sie nicht teilen möchten, und nur die Topic-Branches hochladen, an denen Sie zusammenarbeiten möchten.

Wenn Sie einen Branch namens serverfix haben, an dem Sie mit anderen arbeiten möchten, können Sie ihn auf die gleiche Weise hochladen, wie Sie Ihren ersten Branch hochgeladen haben. Führen Sie git push <remote> <branch> aus.

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

Dies ist eine Art Abkürzung. Git erweitert den Branch-Namen serverfix automatisch zu refs/heads/serverfix:refs/heads/serverfix, was bedeutet: „Nimm meinen lokalen serverfix-Branch und pushe ihn, um den serverfix-Branch des Remotes zu aktualisieren.“ Wir werden den refs/heads/-Teil im Detail in Git Internals behandeln, aber Sie können ihn im Allgemeinen weglassen. Sie können auch git push origin serverfix:serverfix ausführen, was dasselbe tut – es bedeutet: „Nimm mein serverfix und mache es zum serverfix des Remotes.“ Sie können dieses Format verwenden, um einen lokalen Branch in einen Remote-Branch zu pushen, der anders benannt ist. Wenn Sie nicht möchten, dass er auf dem Remote serverfix heißt, könnten Sie stattdessen git push origin serverfix:awesomebranch ausführen, um Ihren lokalen serverfix-Branch in den awesomebranch-Branch des Remote-Projekts zu pushen.

Hinweis
Geben Sie Ihr Passwort nicht jedes Mal ein

Wenn Sie eine HTTPS-URL zum Pushen verwenden, fragt Sie der Git-Server nach Ihrem Benutzernamen und Passwort zur Authentifizierung. Standardmäßig wird er Sie im Terminal nach diesen Informationen fragen, damit der Server feststellen kann, ob Sie zum Pushen berechtigt sind.

Wenn Sie Ihre Anmeldedaten nicht jedes Mal eingeben möchten, wenn Sie pushen, können Sie einen „Credential Cache“ einrichten. Am einfachsten ist es, sie für ein paar Minuten im Speicher zu behalten, was Sie einfach durch Ausführen von git config --global credential.helper cache einrichten können.

Weitere Informationen zu den verschiedenen verfügbaren Optionen zum Zwischenspeichern von Anmeldeinformationen finden Sie unter Credential Storage.

Wenn einer Ihrer Mitarbeiter das nächste Mal vom Server abruft, erhält er eine Referenz darauf, wo sich die Serverversion von serverfix unter dem Remote-Branch origin/serverfix befindet.

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

Es ist wichtig zu beachten, dass Sie, wenn Sie einen Fetch durchführen, der neue Remote-Tracking-Branches herunterlädt, nicht automatisch lokale, bearbeitbare Kopien davon erhalten. Mit anderen Worten, in diesem Fall haben Sie keinen neuen serverfix-Branch – Sie haben nur einen origin/serverfix-Zeiger, den Sie nicht ändern können.

Um diese Arbeit in Ihren aktuellen Arbeits-Branch zusammenzuführen, können Sie git merge origin/serverfix ausführen. Wenn Sie Ihren eigenen serverfix-Branch haben möchten, an dem Sie arbeiten können, können Sie ihn auf Ihrem Remote-Tracking-Branch basieren lassen.

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

Dies gibt Ihnen einen lokalen Branch, an dem Sie arbeiten können, der dort beginnt, wo origin/serverfix ist.

Tracking-Branches

Das Auschecken eines lokalen Branches von einem Remote-Tracking-Branch erstellt automatisch einen sogenannten „Tracking-Branch“ (und der Branch, den er verfolgt, wird als „Upstream-Branch“ bezeichnet). Tracking-Branches sind lokale Branches, die eine direkte Beziehung zu einem Remote-Branch haben. Wenn Sie sich auf einem Tracking-Branch befinden und git pull eingeben, weiß Git automatisch, von welchem Server abgerufen und welcher Branch zusammengeführt werden soll.

Wenn Sie ein Repository klonen, erstellt es im Allgemeinen automatisch einen master-Branch, der origin/master verfolgt. Sie können jedoch auch andere Tracking-Branches einrichten, wenn Sie dies wünschen – solche, die Branches auf anderen Remotes verfolgen, oder die nicht den master-Branch verfolgen. Der einfache Fall ist das Beispiel, das Sie gerade gesehen haben: das Ausführen von git checkout -b <branch> <remote>/<branch>. Dies ist eine so häufige Operation, dass Git die Kurzform --track bereitstellt.

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

Tatsächlich ist dies so üblich, dass es sogar eine Abkürzung für diese Abkürzung gibt. Wenn der Name des Branches, den Sie auschecken möchten (a) nicht existiert und (b) genau mit einem Namen auf nur einem Remote übereinstimmt, erstellt Git automatisch einen Tracking-Branch für Sie.

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

Um einen lokalen Branch mit einem anderen Namen als dem Remote-Branch einzurichten, können Sie ganz einfach die erste Version mit einem anderen lokalen Branch-Namen verwenden.

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'

Nun wird Ihr lokaler Branch sf automatisch von origin/serverfix pullen.

Wenn Sie bereits einen lokalen Branch haben und ihn auf einen gerade heruntergeladenen Remote-Branch einstellen möchten oder den Upstream-Branch ändern möchten, den Sie verfolgen, können Sie die Option -u oder --set-upstream-to von git branch verwenden, um ihn jederzeit explizit festzulegen.

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Hinweis
Upstream-Abkürzung

Wenn Sie einen Tracking-Branch eingerichtet haben, können Sie sich mit der Abkürzung @{upstream} oder @{u} auf seinen Upstream-Branch beziehen. Wenn Sie sich also auf dem master-Branch befinden und dieser origin/master verfolgt, können Sie beispielsweise git merge @{u} anstelle von git merge origin/master sagen, wenn Sie möchten.

Wenn Sie sehen möchten, welche Tracking-Branches Sie eingerichtet haben, können Sie die Option -vv von git branch verwenden. Dies listet Ihre lokalen Branches mit zusätzlichen Informationen auf, einschließlich dessen, was jeder Branch verfolgt, und ob Ihr lokaler Branch voraus, zurück oder beides ist.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

Hier sehen wir, dass unser iss53-Branch origin/iss53 verfolgt und zwei Commits voraus ist, was bedeutet, dass wir zwei Commits lokal haben, die noch nicht auf den Server gepusht wurden. Wir können auch sehen, dass unser master-Branch origin/master verfolgt und auf dem neuesten Stand ist. Als Nächstes sehen wir, dass unser serverfix-Branch den server-fix-good-Branch auf unserem teamone-Server verfolgt und drei Commits voraus und einen Commit zurück ist, was bedeutet, dass ein Commit auf dem Server vorhanden ist, den wir noch nicht zusammengeführt haben, und drei Commits lokal, die wir noch nicht gepusht haben. Schließlich können wir sehen, dass unser testing-Branch keinen Remote-Branch verfolgt.

Es ist wichtig zu beachten, dass diese Zahlen nur seit dem letzten Abruf von jedem Server gelten. Dieser Befehl greift nicht auf die Server zu, er informiert Sie über das, was er lokal von diesen Servern zwischengespeichert hat. Wenn Sie vollständig aktuelle Zahlen für „voraus“ und „zurück“ haben möchten, müssen Sie sich von allen Ihren Remotes abrufen, bevor Sie dies ausführen. Sie könnten das so tun:

$ git fetch --all; git branch -vv

Pulling

Während der Befehl git fetch alle Änderungen auf dem Server abruft, die Sie noch nicht haben, ändert er Ihr Arbeitsverzeichnis überhaupt nicht. Er holt nur die Daten für Sie und lässt Sie sie selbst zusammenführen. Es gibt jedoch einen Befehl namens git pull, der im Wesentlichen ein git fetch ist, gefolgt von einem git merge in den meisten Fällen. Wenn Sie einen Tracking-Branch eingerichtet haben, wie im letzten Abschnitt gezeigt, entweder durch explizites Festlegen oder durch automatische Erstellung durch die Befehle clone oder checkout, sucht git pull, von welchem Server und welchem Branch Ihr aktueller Branch verfolgt wird, ruft von diesem Server ab und versucht dann, diesen Remote-Branch zusammenzuführen.

Löschen von Remote-Branches

Angenommen, Sie sind mit einem Remote-Branch fertig – sagen wir, Sie und Ihre Mitarbeiter haben eine Funktion abgeschlossen und sie in den master-Branch Ihres Remotes (oder welchen Branch auch immer Ihre stabile Codezeile ist) zusammengeführt. Sie können einen Remote-Branch mit der Option --delete von git push löschen. Wenn Sie Ihren serverfix-Branch vom Server löschen möchten, führen Sie Folgendes aus:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

Im Grunde entfernt dies nur den Zeiger vom Server. Der Git-Server behält die Daten normalerweise eine Weile, bis eine Garbage Collection ausgeführt wird. Wenn sie also versehentlich gelöscht wurde, ist sie oft leicht wiederherzustellen.