Git
Chapters ▾ 2nd Edition

3.5 Branchen in Git - Branches op afstand (Remote branches)

Branches op afstand (Remote branches)

Remote branches zijn referenties (pointers) naar jouw remote repositories, inclusief branches, tags, enz. Je kunt een volledige lijst van remote referenties expliciet krijgen met git ls-remote [remote] of ook git remote show [remote] voor zowel remote branches als voor meer informatie. Niettemin is heth gebruikelijker om te profiteren van remote-tracking branches.

Remote-tracking branches zijn referenties naar de staat van remote branches. Het zijn lokale referenties die je niet kunt verplaatsen; Git verplaatst ze automatisch voor je op de momenten dat je een vorm van netwerk communicatie uitvoert, dit om te verzekeren dat ze een accurate representatie zijn van de staat van de remote repository. Remote-tracking branches gedragen zich als boekenleggers om je eraan te helpen herinneren wat de staat van de branches was van je remote repositories toen je voor het laatst met ze in contact was.

Remote-tracking branch namen hebben de vorm <remote>/<branch>. Bijvoorbeeld, als je wil zien hoe de master-branch op je origin remote er uitzag de laatste keer dat je er mee communiceerde, dan zal je de origin/master-branch moeten bekijken. Als je samen met een partner aan het werk bent met een probleem en zij heeft een iss53-branch gepusht, is het niet onmogelijk dat je zelf een eigen lokale iss53 hebt, maar de branch op de server zal vertegenwoordigd zijn door de remote-tracking branch origin/iss53.

Dit kan wat verwarrend zijn, dus laten we eens naar een voorbeeld kijken. Stel dat je een Git-server in je netwerk hebt op git.ourcompany.com. Als je hiervan kloont dan wordt die door het clone commando van Git automatisch origin voor je genoemd, Git haalt alle gegevens binnen, maakt een verwijzing naar waar de master-branch is en noemt dat lokaal origin/master. Git geeft je ook een eigen lokale master-branch, beginnend op dezelfde plaats als de master-branch van origin, zodat je iets hebt om vanaf te werken.

Noot
“origin” is niets speciaal

Net als de branch naam “master” geen enkele speciale betekenis heeft in Git, heeft “origin” dat ook niet. Waar “master” de standaard naam is voor een branch die dient als beginpunt als je git init aanroept, wat de enige reden is waarom het zo vaak wordt gebruikt, is “origin” de standaard naam voor een remote als je git clone aanroept. Als je git clone -o booyah gebruikt, krijg je booyah/master als je standaard remote branch.

Server en lokale repositories na klonen.
Figuur 30. Server en lokale repositories na klonen

Als je wat werk doet op je lokale master-branch, en in de tussentijd pusht iemand anders iets naar git.ourcompany.com waardoor die master-branch wordt vernieuwd, dan zijn jullie histories verschillend vooruit geschoven. En zolang je geen contact hebt met de origin server, zal jouw origin/master verwijzing niet verplaatsen.

Lokaal en remote werk kan gaan afwijken.
Figuur 31. Lokaal en remote werk kan gaan afwijken

Om je werk te synchroniseren met een gegeven remote, voer je een git fetch <remote> commando uit (in ons geval, git fetch origin). Dit commando bekijkt welke server “origin” is (in dit geval is het git.ourcompany.com), haalt gegevens er vanaf die je nog niet hebt en vernieuwt je lokale database, waarbij je origin/master-verwijzing naar zijn nieuwe positie verplaatst wordt die meer up-to-date is.

`git fetch` vernieuwt je remote referenties.
Figuur 32. git fetch vernieuwt je remote referenties

Om het hebben van meerdere remote servers te demonstreren en hoe remote branches voor die remote projecten er uitzien, zullen we aannemen dat je nog een interne Git-server hebt die alleen wordt gebruikt voor ontwikkelingen gedaan door een van je sprint teams. Deze server bevindt zich op git.team1.ourcompany.com. Je kunt het als een nieuwe remote referentie toevoegen aan het project waar je nu aan werkt door het git remote add commando uit te voeren, zoals we behandeld hebben in Git Basics. Noem deze remote teamone, wat jouw afkorting voor die hele URL wordt.

Een andere server toevoegen als remote.
Figuur 33. Een andere server toevoegen als remote

Nu kun je git fetch teamone uitvoeren om alles op te halen dat wat de teamone remote server heeft en jij nog niet. Omdat die server een subset heeft van de gegevens die jouw origin server op dit moment heeft, haalt Git geen gegevens op maar maakt een remote-tracking branch genaamd teamone/master aan en laat die wijzen naar de commit die teamone heeft als zijn master-branch.

Remote tracking branch voor `teamone/master`.
Figuur 34. Remote tracking branch voor teamone/master

Pushen

Als je een branch wil delen met de rest van de wereld, dan moet je het naar een remote terugzetten waar je schrijftoegang op hebt. Je lokale branches worden niet automatisch gesynchroniseerd met de remotes waar je naar schrijft — je moet de branches die je wilt delen expliciet pushen. Op die manier kun je privé branches gebruiken voor het werk dat je niet wil delen, en alleen die topic branches pushen waar je op wilt samenwerken.

Als je een branch genaamd serverfix hebt waar je met anderen aan wilt werken, dan kun je die op dezelfde manier pushen als waarop je dat voor de eerste branch hebt gedaan. Voer git push <remote> <branch< uit:

$ 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

Dit is wel een beetje de bocht afsnijden. Git zal de serverfix-branchnaam automatisch expanderen naar refs/heads/serverfix:refs/heads/serverfix, wat staat voor “Neem mijn lokale serverfix branch en push die om de serverfix branch van de remote te vernieuwen.”. We zullen het refs/heads gedeelte gedetaileerd behandelen in Git Binnenwerk, maar je kunt het normaalgesproken weglaten. Je kun ook git push origin serverfix:serverfix doen, wat hetzelfde doet. Dit staat voor “Neem mijn serverfix en maak het de serverfix van de remote.” Je kunt dit formaat gebruiken om een lokale branch te pushen naar een remote branch die anders heet. Als je niet wil dat het serverfix heet aan de remote kant, kan je in plaats daarvan git push origin serverfix:awesomebranch gebruiken om je lokale serverfix-branch naar de awesomebranch op het remote project te pushen.

Noot
Type niet elke keer je wachtwoord

Als je een HTTPS URL gebruikt om mee te pushen, zal de Git server je elke keer vragen naar je usernaam en wachtwoord voor authenticatie. Standaard zal het je via de terminal vragen (prompten) om deze informatie zodat de server kan vaststellen of je mag pushen.

Als je dit niet elke keer wilt intypen als je pusht, kan je een “credential cache” opzetten. Het eenvoudigste is om het gewoon in het geheugen te houden voor een aantal minuten. Dit kan je simpel opzetten door git config --global credential.helper cache aan te roepen.

Voor meer informatie over de verschillende beschikbare credential caching opties, zie Het opslaan van inloggegevens.

De volgende keer dat één van je medewerkers van de server fetcht zal deze een referentie krijgen naar de versie van serverfix op de server, onder de remote branch origin/serverfix:

$ 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

Het is belangrijk om op te merken dat wanneer je een fetch doet die nieuwe remote-tracking branches ophaalt, je niet automatisch lokale aanpasbare kopieën daarvan hebt. In andere woorden, in dit geval heb je geen nieuwe serverfix-branch — je hebt alleen een origin/serverfix verwijzing die je niet kunt aanpassen.

Om dit werk in je huidige werk branch te mergen, kun je git merge origin/serverfix uitvoeren. Als je een eigen serverfix-branch wilt waar je op kunt werken, dan kun je deze op je remote-tracking branch baseren:

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

Dit maakt een lokale branch aan waar je op kunt werken, die begint waar origin/serverfix is.

Tracking branches

Een lokale branch uitchecken van een remote-tracking branch creëert automatisch een zogenoemde “tracking branch” (“volg branch”, en de branch die hij volgt heet een “upstream branch”). Tracking branches zijn lokale branches die een directe releatie met een remote branch hebben. Als je op een tracking branch zit en git pull typt, dat weet Git automatisch naar welke server moet gaan om de wijzigingen op te halen en in welke branch deze moeten worden gemerged.

Als je een repository kloont, zal het over het algemeen automatisch een master-branch aanmaken die origin/master trackt. Maar je kan ook andere tracking branches aanmaken als je dat wilt — andere die branches op andere remotes tracken, of niet de master-branch tracken. Een eenvoudig voorbeeld is wat je zojuist gezien hebt: git checkout -b <branch> <remotenaam>/<branch> uitvoeren. Deze operatie komt dusdanig vaak voor dat Git de --track afkorting levert:

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

Sterker nog, dit is zo gewoon dat er zelfs een afkorting voor de afkorting is. Als de branch naam die je uit wilt checken (a) niet bestaat en (b) dezelfde naam maar op een remote voorkomt, zal Git een tracking branch voor je aanmaken:

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

Om een lokale branch te maken met een andere naam dan de remote branch, kun je simpelweg de eerste variant met een andere lokale branchnaam gebruiken:

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

Nu zal je lokale sf-branch automatisch pullen van origin/serverfix.

Als je al een lokale branch hebt en je wilt deze koppelen aan een remote branch die je zojuist gepulld hebt, of de stroomopwaartse branch die je trackt wijzigen, kan je de -u of --set-upstream-to optie gebruiken bij de git branch om het expliciet te zetten op de momenten dat jij het wilt.

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Noot
Upstream verwijzing

Als je een tracking branch ingericht hebt, kan je hiernaar refereren met de @{upstream} of @{u} verwijzing. Dus als je op de master-branch zit en deze origin/master trackt, kan je iets als git merge @{u} opgeven in plaats van git merge origin/master als je zou willen.

Als je wilt zien welke tracking branches je ingericht hebt, kan je de -vv optie aan git branch meegeven. Dit zal jouw lokale branches afdrukken met meer informatie, inclusief wat elk van de branches trackt en of je lokale branch voorloopt, acherloopt of beide.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new

Dus hier kunnen we zien dat onze iss53 origin/iss53 trackt en twee “voorloopt”, wat inhoudt dat we lokaal twee commits hebben die nog niet naar de server zijn gepusht. We kunnen ook zien dat onze master-branch origin/master trackt en up-to-date is. Vervolgens zien we dat onze serverfix-branch de server-fix-good-branch trackt op onze teamone server en drie voorloopt en een achterloopt. Dit betekent dat er een commit op de server staat die we nog niet hebben gemerged en er drie commits lokaal staan die we nog niet gepusht hebben. Tenslotte kunnen we zien dat onze testing-branch geen enkele remote branch trackt.

Het is belangrijk om op te merken dat deze getallen accuraat zijn op het moment dat je voor het laatst gefetcht hebt van elke server. Dit commando maakt geen contact met de servers, het vertelt je wat het van deze servers lokaal heeft opgeslagen. Als je volledige up-to-date gegevens wilt hebben over voorsprong en achterstand zal je van alle remotes moeten fetchen voordat je dit aanroept. Je zou iets als volgt kunnen doen:

$ git fetch --all; git branch -vv

Pullen

Waar het git fetch commando alle wijzigingen van de server zal ophalen die je nog niet hebt, zal het je werk directory helemaal niet wijzigen. Het haalt simpelweg de gegevens voor je op en laat het mergen aan jou over. Er is echter een commando git pull geheten die feitelijk een git fetch onmiddelijk gevolgd door een git merge is in de meeste gevallen. Als je een tracking branch opgezet hebt zoals in de vorige paragraaf getoond, expliciet opgezet of voor je opgezet door de clone of checkout commando’s, zal git pull kijken welke server en branch je huidige branch trackt, van die server fetchen en de betreffende remote branch daarin mergen.

Over het algemeen is het beter om de fetch en merge commando’s expliciet te gebruiken omdat de magie van git pull vaak verwarrend kan zijn.

Remote branches verwijderen

Stel dat je klaar bent met een remote branch - zeg maar, jij en je medewerkers zijn klaar met een feature en hebben het gemerged in de master-branch van de remote (of welke branch jullie stabiele code ook in zit). Je kunt een remote branch verwijderen met de --delete optie bij git push. Als je de serverfix-branch van de server wilt verwijderen, dan voer je het volgende uit:

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

Alles wat dit doet is de pointer van de server verwijderen. De Git server zal over het algemeen de gegevens nog een poos behouden totdat de garbage collection draait, dus als het per ongeluk verwijderd is, is het vaak eenvoudig terug te halen.

scroll-to-top