Git
Chapters ▾ 2nd Edition

3.5 Git Branching - Remote-Branches

Remote-Branches

Remote-Referenzen sind Referenzen (Zeiger) in Ihren Remote-Repositorys, einschließlich Branches, Tags usw. Sie können eine vollständige, ausführliche Liste von Remote-Referenzen bekommen, wenn Sie die Anweisungen git ls-remote <remote> oder git remote show <remote> ausführen, für Remote-Branches sowie für weitere Informationen. Der gebräuchlichste Ansatz ist jedoch die Nutzung von Remote-Tracking-Branches.

Remote-Tracking-Branches sind Referenzen auf den Zustand von Remote-Branches. Sie sind lokale Referenzen, die Sie nicht manuell ändern können, sie werden automatisch für Sie geändert, sobald Sie irgendeine Netzwerkkommunikation durchführen. Betrachten Sie sie als Lesezeichen, die Sie daran erinnern, wo die Branches in Ihren Remote-Repositorys das letzte Mal standen, als Sie sich mit ihnen verbunden hatten.

Remote-Tracking-Branch-Namen haben die Form <remote>/<branch>. Wenn Sie beispielsweise wissen möchten, wie der Branch master in Ihrem Repository origin ausgesehen hat, als Sie zuletzt Kontakt mit ihm hatten, dann würden Sie den Branch origin/master überprüfen. Wenn Sie mit einem Mitarbeiter an einem Problem gearbeitet haben und dieser bereits einen iss53 Branch hochgeladen (gepusht) hat, besitzen Sie möglicherweise Ihren eigenen lokalen iss53 Branch; aber der Branch auf dem Server würde auf den Remote-Tracking-Branch origin/iss53 zeigen.

Das kann ein wenig verwirrend sein, lassen Sie uns also ein Beispiel betrachten. Angenommen, Sie haben in Ihrem Netzwerk einen Git-Server mit der Adresse git.ourcompany.com. Wenn Sie von diesem klonen, erhält der Server von der Git-Anweisung clone automatisch den Namen origin, lädt all seine Daten herunter, erstellt einen Zeiger zu dem Commit, auf den dessen master Branch zeigt und benennt ihn lokal origin/master. Git gibt Ihnen auch Ihren eigenen lokalen master Branch mit der gleichen Ausgangsposition wie der origin/master Branch, damit Sie einen Punkt haben, wo Sie mit Ihrer Arbeit beginnen können.

Note
„origin“ ist nichts Besonderes

Genau wie der Branch-Name „master“ in Git keine besondere Bedeutung hat, hat auch „origin“ keine besondere Bedeutung. Während „master“ die Standardbezeichnung für einen Anfangsbranch ist, wenn Sie die Anweisung git init ausführen, was der einzige Grund dafür ist, warum er so weit verbreitet ist, wird „origin“ als Standardbezeichnung für ein entferntes Repository vergeben, wenn Sie die Anweisung git clone ausführen. Wenn Sie stattdessen die Anweisung git clone -o booyah ausführen, erhalten Sie booyah/master als Standard-Remote-Branch.

Entfernte und lokale Repositorys nach dem Klonen
Figure 30. Entfernte und lokale Repositorys nach dem Klonen

Wenn Sie ein wenig an Ihrem lokalen master Branch arbeiten und in der Zwischenzeit jemand anderes etwas zu git.ourcompany.com hochlädt und damit dessen master Branch aktualisiert, dann bewegen sich eure Verläufe unterschiedlich vorwärts. Und solange Sie keinen Kontakt mit Ihrem origin Server aufnehmen, bewegt sich Ihr origin/master Zeiger nicht.

Lokale und entfernte Änderungen können Auseinanderlaufen
Figure 31. Lokale und entfernte Änderungen können Auseinanderlaufen

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

`git fetch` aktualisiert Ihre Remote-Tracking-Branches
Figure 32. git fetch aktualisiert Ihre Remote-Tracking-Branches

Um den Umgang mit mehreren Remote-Servern zu veranschaulichen und um zu sehen, wie Remote-Branches bei diesen Remote-Projekten aussehen, nehmen wir an, dass Sie einen weiteren internen Git-Server haben, welcher von einem Ihrer Sprint-Teams nur zur Entwicklung genutzt wird. Diesen Server erreichen wir unter git.team1.ourcompany.com. Sie können ihn zu dem Projekt, an dem Sie gegenwärtig arbeiten, als neuen Remote-Server hinzufügen, indem Sie die Anweisung git remote add ausführen, wie wir bereits in Kapitel 2 Git Grundlagen behandelt haben. Wir nennen diesen Remote-Server teamone, was die Kurzbezeichnung für die gesamte URL sein wird.

Hinzufügen eines weiteren Remote-Servers
Figure 33. Hinzufügen eines weiteren Remote-Servers

Jetzt können Sie mit der Anweisung git fetch teamone alles vom Server holen, was Sie noch nicht haben. Da auf diesem Server nur eine Teilmenge der Daten ist, die sich genau jetzt auf Ihrem origin Server befinden, holt Git keine Daten ab, aber es erstellt einen Remote-Branch teamone/master so, dass er auf den Commit zeigt, den teamone als seinen master Branch hat.

Remote-Tracking-Branch für `teamone/master`
Figure 34. Remote-Tracking-Branch für teamone/master

Pushing/Hochladen

Wenn Sie einen Branch mit der Welt teilen möchten, müssen Sie ihn auf einen Remote-Server hochladen, auf dem Sie Schreibrechte besitzen. Ihre lokalen Branches, auf die Sie schreiben, werden nicht automatisch mit den Remotes synchronisiert – Sie müssen die Branches, die Sie freigeben möchten, explizit pushen. Auf diese Weise können Sie private Branches, die Sie nicht veröffentlichen wollen, zum Arbeiten benutzen und nur die Themen-Branches pushen, an denen Sie mitarbeiten wollen.

Wenn Sie einen Zweig namens serverfix besitzen, an dem Sie mit anderen arbeiten möchten, dann können Sie diesen auf dieselbe Weise Hochladen wie Ihren ersten Branch. Führen Sie die Anweisung 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

Das ist eine Art Abkürzung. Git erweitert den Branch-Namen serverfix automatisch zu refs/heads/serverfix:refs/heads/serverfix, was soviel bedeutet wie „Nimm meinen lokalen Branch serverfix und aktualisiere damit den serverfix Branch auf meinem Remote-Server“. Wir werden den Teil refs/heads/ in Kapitel 10 Git Interna noch näher beleuchten, Sie können ihn aber in der Regel auslassen. Sie können auch die Anweisung git push origin serverfix:serverfix ausführen, was das Gleiche bewirkt – es bedeutet „Nimm meinen serverfix und mach ihn zum serverfix des Remote-Servers“. Sie können dieses Format auch benutzen, um einen lokalen Branch in einen Remote-Branch mit anderem Namen zu pushen. Wenn Sie nicht wollten, dass er auf dem Remote als serverfix bezeichnet wird, können Sie stattdessen git push origin serverfix:awesomebranch ausführen, um Ihren lokalen serverfix Branch auf den awesomebranch Branch im Remote-Projekt zu pushen.

Note
Geben Sie Ihr Passwort nicht jedes Mal neu ein

Wenn Sie eine HTTPS-URL zum Übertragen verwenden, fragt Sie der Git-Server nach Ihrem Benutzernamen und Passwort zur Authentifizierung. Standardmäßig werden Sie auf dem Terminal nach diesen Informationen gefragt, damit der Server erkennen kann, ob Sie pushen dürfen.

Wenn Sie es nicht jedes Mal eingeben wollen, wenn Sie etwas hochladen, dann können Sie einen „credential cache“ einstellen. Am einfachsten ist es, die Informationen nur für einige Minuten im Speicher zu behalten, was Sie einfach mit der Anweisung git config --global credential.helper cache bewerkstelligen können.

Weitere Informationen zu den verschiedenen verfügbaren „credential cache“ Optionen finden Sie in Kapitel 7 Caching von Anmeldeinformationen.

Das nächste Mal, wenn einer Ihrer Mitarbeiter Daten vom Server abholt, wird er eine Referenz auf die Server-Version des Branches serverfix unter dem Remote-Branch origin/serverfix erhalten:

$ 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 wissen, dass, wenn Sie einen Fetch durchführen, dass neue Remote-Tracking-Branches heruntergeladen werden, Sie nicht automatisch lokale, bearbeitbare Kopien von ihnen haben. Mit anderen Worten, in diesem Fall haben Sie keinen neuen Branch serverfix – Sie haben nur einen Zeiger origin/serverfix, den Sie nicht ändern können.

Um diese Änderungen in Ihren gegenwärtigen Arbeitsbranch einfließen zu lassen, können Sie die Anweisung git merge origin/serverfix ausführen. Wenn Sie Ihren eigenen serverfix Branch haben wollen, an dem Sie arbeiten können, können Sie ihn von Ihrem Remote-Tracking-Branch ableiten (engl. base):

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

Das erstellt Ihnen einen lokalen Branch, an dem Sie arbeiten können, und der dort beginnt, wo origin/serverfix derzeit steht.

Tracking-Branches

Das Auschecken eines lokalen Branches von einem Remote-Branch erzeugt automatisch einen sogenannten „Tracking-Branch“ (oder manchmal einen „Upstream-Branch“). 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 Daten abzuholen sind und in welchen Branch diese einfließen sollen.

Wenn Sie ein Repository klonen, wird automatisch ein master Branch erzeugt, welcher origin/master trackt. Sie können jedoch auch andere Tracking-Branches erzeugen, wenn Sie wünschen – welche die Branches auf anderen Remotes verfolgen. Der einfachste Fall ist das Beispiel, dass Sie gerade gesehen haben, die Ausführung der Anweisung git checkout -b <branch> <remotename>/<branch>. Das ist eine übliche Operation, für die 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'

In der Tat ist dies so weit verbreitet, dass es sogar eine Abkürzung für diese Abkürzung gibt. Wenn der Branch-Name, den Sie zum Auschecken verwenden möchten (a), nicht existiert und (b) genau mit einem Namen auf nur einem Remote übereinstimmt, erstellt Git 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 den entfernten Branch einzurichten, können Sie 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 gepullt.

Wenn Sie bereits einen lokalen Branch haben und diesen auf einen Remote-Branch einstellen möchten, den Sie gerade abgerufen (gepullt) haben, oder wenn Sie den Upstream-Branch ändern möchten, den Sie versionieren, könnten Sie die Option -u oder --set-upstream-to zusammen mit git branch verwenden, um sie zu einem beliebigen Zeitpunkt explizit festzulegen.

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Note
Upstream-Kürzel

Wenn Sie einen Tracking-Branch eingerichtet haben, können Sie auf seinen Upstream-Branch mit der Kurzform @{upstream} oder @{u} verweisen. Wenn Sie also auf dem master Branch sind und er origin/master versioniert, können Sie, wenn Sie möchten, so etwas wie git merge @{u} anstelle von git merge origin/master verwenden.

Wenn Sie die Tracking-Branches sehen wollen, die Sie eingerichtet haben, können Sie die Anweisung git branch zusammen mit der Option -vv ausführen. Das listet Ihre lokalen Branches zusammen mit weiteren Informationen auf, einschließlich was jeder Branch versioniert/trackt und ob Ihr lokaler Branch voraus, hinterher 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 können wir also sehen, dass unser iss53 Branch den Branch origin/iss53 verfolgt und die Information „ahead 2“ bedeutet, dass wir zwei lokale Commits haben, welche noch nicht auf den Server hochgeladen wurden. Wir können außerdem sehen, dass unser master Branch origin/master verfolgt und auf den neuesten Stand ist. Als nächstes sehen wir, dass unser serverfix Branch den Branch server-fix-good auf unserem Server teamone versioniert und „ahead 3, behind 1“ bedeutet, dass es einen Commit auf dem Server gibt, den wir noch nicht gemergt haben, und drei lokale Commits existieren, die wir noch nicht gepusht haben. Zum Schluss können wir sehen, dass unser testing Branch gar keinen Remote-Branch verfolgt.

Es ist wichtig zu beachten, dass diese Zahlen den Zustand zu dem Zeitpunkt beschreiben, als Sie zum letzten Mal Daten vom Server abgeholt haben. Diese Anweisung greift nicht auf die Server zu, sie liefert nur die Informationen, welche beim letzten Server-Kontakt lokal zwischengespeichert wurden. Wenn Sie gänzlich aktuelle Zahlen von „ahead“ und „behind“ wollen, dann müssen Sie, kurz bevor Sie die Anweisung ausführen, von all Ihren Remote-Servern Daten abholen (fetch). Sie könnten das so machen:

$ git fetch --all; git branch -vv

Pulling/Herunterladen

Während die Anweisung git fetch alle Änderungen auf dem Server abholt, die Sie zurzeit noch nicht haben, wird sich aber an Ihrem Arbeitsverzeichnis überhaupt nichts verändern. Sie wird einfach die Daten für Sie holen und Ihnen das Zusammenführen überlassen. Es gibt jedoch die Anweisung git pull, welche im Grunde genommen ein git fetch ist, dem in den meisten Fällen augenblicklich ein git merge folgt. Wenn Sie einen Tracking-Branch eingerichtet haben, wie im letzten Abschnitt gezeigt, entweder indem Sie ihn explizit setzen oder indem Sie ihn mit den Befehlen clone oder checkout für sich haben erstellen lassen, dann sucht git pull nach dem Server und dem versionierten Branch, verzweigt zu Ihrem aktuellen Branch, pullt von diesem Server und versucht dann, diesen Remote-Branch zu mergen.

Generell ist es besser, einfach explizit die Anweisungen git fetch und git merge zu benutzen, da die Zauberei der Anweisung git pull häufig verwirrend sein kann.

Remote-Branches Entfernern

Stellen wir uns vor, Sie sind mit Ihrem Remote-Branch fertig – Sie und Ihre Mitarbeiter sind fertig mit einer neuen Funktion und haben sie in den Branch master des Remote-Servers (oder in welchem Branch auch immer sich Ihr stabiler Code befindet) einfließen lassen. Sie können einen Remote-Branch löschen, indem die Anweisung git push zusammen mit der Option --delete ausführen. Wenn Sie Ihren serverfix Branch vom Server löschen wollen, führen Sie folgende Anweisung aus:

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

Im Grunde genommen ist alles, was das bewirkt, dass der Zeiger vom Server entfernt wird. Der Git-Server bewahrt die Daten dort in der Regel eine Weile auf, bis eine Speicherbereinigung läuft. Wenn sie also versehentlich gelöscht wurden, ist es oft einfach, sie wiederherzustellen.