Remotes og clone: tre ting som heter main
Den interaktive leksjonen trenger JavaScript. Teksten under er hele leksjonen.
Etter leksjonen kan du
- forklare at en remote bare er et annet repository, og at
originbare er et lokalt navn på adressen forstå - koble et repository til en remote med
git remote add, og kopiere et repository medgit cloneanvende - skille mellom din
main, din remote-tracking-branchorigin/mainogmaininne i origin forstå - sette upstream for en branch, og lese med
git branch -vvhvilken upstream den følger og hvor langt foran eller bak den er anvende
Forstå: Et repository til
Til nå har du jobbet i ett repository på din egen maskin. For å samarbeide trenger teamet et repository som alle kan nå. Et repository som ditt kjenner til, kalles en remote. Det kan ligge på GitHub, på en skoleserver eller i en vanlig mappe.
Repositoryet ditt har en kort liste over remotes, hver med et navn og en adresse. Det vanlige navnet er origin. Det er bare et lokalt kallenavn, ikke en spesiell server. I figuren heter main inne i origin origin:main, et merke bare figuren bruker.
git clone kopierer et helt repository: hele historikken som branchene og taggene når, ikke bare de nyeste filene. Clone legger også til remoten origin og sjekker ut standardbranchen, her main. Etterpå kjenner begge repositoryene de samme commitene.
Nå finnes det tre ting som heter main. main er din egen branch. origin:main er branchen inne i origin. Og origin/main er en remote-tracking-branch i ditt repository: Gits notat om hvor main i origin sto sist du snakket med origin.
Se hva som skjer når du committer C. Bare din main flytter seg. Origin vet ingenting før du sender commiten dit, og origin/main husker fortsatt B. Du er én commit foran.
Din main husker også hvilken remote-tracking-branch den følger, her origin/main. Det kalles branchens upstream. Derfor vet git status og git push hva de skal sammenligne med. git branch -vv viser upstream i hakeparentes, sammen med hvor langt foran eller bak du er.
Se demo: Lag et delt repository og klon det
Vi har et repository med én commit. Først lager vi et delt repository som teamet kan bruke. Et bare repository har bare historikk og ingen arbeidsfiler. Det er det en server oppbevarer.
$ git init --bare /course/origin.git
Nå gir vi adressen et navn i vårt repository. Vi kaller den origin, som er vanlig. Grafen endrer seg ikke. Vi har bare skrevet et navn og en sti i en liste.
$ git remote add origin /course/origin.git
git remote -v viser listen. Vi ser én adresse for fetch og én for push. Her er det bare en mappe på samme maskin.
$ git remote -v
Nå sender vi main til origin. Valget -u lagrer samtidig at main skal følge main i origin. Før pushen er origin tom, og du har ingen origin/main.
$ git push -u origin main
Ada blir med i prosjektet. Hun kloner det delte repositoryet til sin egen mappe. Hennes main dukker opp i grafen som ada:main, på samme commit. Hun har fått hele historikken.
$ git clone /course/origin.git /course/ada
Tilbake hos deg lager vi en ny commit lokalt. Vi pusher den ikke.
$ echo "Draft" > notes.txt && git add notes.txt && git commit -m "Add notes"
git branch -vv viser upstream i hakeparentesen, origin/main, og at du er én commit foran. I grafen står origin/main og origin:main fortsatt på den gamle commiten.
$ git branch -vv
Oppgaver
- Lag et tomt bare repository i
/course/origin.gitsom skal være teamets felles repository. - Registrer det delte repositoryet som en remote med navnet origin.
- Vis hvilke remotes repositoryet kjenner, med adresser.
- Publiser main til origin, og sett origin/main som upstream.
- Lag Adas kopi av det delte repositoryet i
/course/ada. - Vis branchene dine med upstream og hvor langt foran du er.
Øv: Overfør: en ny kollega og en glemt upstream
Et delt repository finnes allerede, og main er pushet dit, men uten -u. Ada har ingen kopi ennå.
Oppgaver
- Din main har ingen upstream, så
git statussammenligner ikke med noe. Få main til å følge origin/main, uten å lage nye commits. - Ada begynner i teamet. Gi henne en egen kopi av det delte repositoryet i
/course/ada. - Tilbake i ditt repository: teamet vil heller kalle det delte repositoryet
shared. Gi remoten nytt navn, og bekreft at upstream du satte for main, nå heter shared/main.
Sjekk deg selv: Hent det fram igjen
Hva er origin?
- GitHubs sentrale server
- Et navn i ditt repository for adressen til et annet repository
- En spesiell branch som alltid har den nyeste versjonen
Ada kloner det delte repositoryet og går offline. Kan hun se den aller første commiten med git log?
- Nei. Clone kopierer bare de nyeste filene, så eldre commits må hentes fra origin.
- Ja. Clone kopierte historikken, så log leser den fra hennes eget repository.
- Bare hvis hun kjørte
git pullfør hun gikk offline
git branch -vv viser [origin/main: behind 2]. Hva betyr det?
- Serveren har akkurat nå nøyaktig to commits du mangler
- Du har to commits som ikke er pushet
- origin/main har to commits som din main mangler, slik det var sist du snakket med origin
Repetisjon fra modul 2: hva er en branch, for eksempel main?
- En kopi av prosjektmappen
- Et navn som peker på én commit, og som flytter seg når du committer på den
- En liste over endringene siden branchen ble laget
Vanlige misforståelser
- «origin er GitHub» eller «origin er serveren». origin er bare navnet ditt repository bruker på en adresse. Adressen kan like gjerne være en mappe på samme disk, og navnet kan endres.
- «origin/main viser serveren akkurat nå.» origin/main er en remote-tracking-branch i ditt repository. Den viser hvor main i origin var sist du snakket med origin.
- «clone henter bare de nyeste filene.» En vanlig clone kopierer hele historikken som branchene og taggene når.
Les mer
En remote er et navn på en adresse
En remote er en liten blokk i konfigurasjonen til repositoryet ditt: et kort navn, en URL og en regel for hva fetch lagrer. git remote add origin /course/origin.git laster ikke ned noe og kontakter ingen. Den skriver bare dette inn i .git/config:
[remote "origin"]
url = /course/origin.git
fetch = +refs/heads/*:refs/remotes/origin/*
URL-en kan være https://…, en SSH-adresse som git@example.org:team/project.git, eller en vanlig mappesti slik som i dette kurset. Git behandler alle likt; bare transporten er forskjellig. Innlogging hos en hostingtjeneste hører til transporten, ikke til git config user.name, som bare setter navn på commitene dine.
Administrere remotes
| Kommando | Hva den gjør |
|---|---|
git remote -v |
List alle remotes med adresse for fetch og push. |
git remote add upstream URL |
Legg til enda en remote under et nytt navn. |
git remote rename origin shared |
Gi en remote nytt navn. Remote-tracking-brancher og upstream-innstillinger får også nytt navn. |
git remote set-url origin URL |
Endre adressen, for eksempel når prosjektet flytter eller du bytter fra HTTPS til SSH. |
git remote remove upstream |
Glem navnet og remote-tracking-branchene. Det andre repositoryet røres ikke. |
git remote show origin |
Kontakt remoten og oppsummer standardbranch, sporede brancher og hva git pull og git push vil gjøre. |
Hva git clone egentlig gjør
Clone er et lite skript av steg du allerede kjenner:
- Lag mappen og kjør
git initi den. - Legg til en remote som heter
origin, med adressen du oppga. - Hent alle brancher og tagger, med alle commitene de når. Hver branch i remoten blir en remote-tracking-branch, som
origin/mainellerorigin/docs. - Lag én lokal branch, remotens standardbranch, sett upstream og sjekk den ut.
Etter at du har klonet et prosjekt med branchene main og docs, har du altså origin/docs, men ingen lokal docs. Det er ikke et problem: git switch docs merker at nøyaktig én remote har en branch med det navnet, lager en lokal docs fra origin/docs og setter upstream for deg. Clone kopierer historikk, ikke konfigurasjon: lokale innstillinger, hooks og stasher i originalen blir igjen.
Refspecs: regelen bak origin/main
fetch-linjen over er en refspec, en oversettelse fra navn i remoten til navn her. Les +refs/heads/*:refs/remotes/origin/* fra venstre mot høyre: ta alle brancher i remoten og lagre dem under refs/remotes/origin/ i mitt repository. Plusstegnet lar disse notatene flytte seg selv om remote-branchen er skrevet om.
To ting følger av dette. For det første er origin/main bare kortform for refs/remotes/origin/main, en helt vanlig ref i ditt repository. For det andre flytter en vanlig git fetch aldri din egen main, fordi standard-refspecen bare skriver inn i refs/remotes/origin/. Push bruker også refspecs: git push origin main betyr «la main der borte peke dit min main peker», og git push origin feature:review publiserer din lokale feature som en branch som heter review i remoten. Å slette en remote-branch er en push av ingenting: git push origin :review, som er det samme som git push origin --delete review.
Upstream: hva en branch følger
git push -u origin main lagrer to innstillinger, som du kan lese tilbake:
$ git config --get-regexp '^branch\.main\.'
branch.main.remote origin
branch.main.merge refs/heads/main
Sammen er de branchens upstream. git status bruker den til «ahead» og «behind», og git pull og git push uten argumenter bruker den som mål. Kortformen @{u} betyr upstream i alle kommandoer: git log @{u}.. lister commits du ikke har pushet, og git log ..@{u} lister commits du har hentet, men ikke integrert.
| Du vil | Kommando |
|---|---|
| Sette upstream mens du publiserer | git push -u origin feature |
| Sette den på en eksisterende branch | git branch -u origin/main |
| Fjerne den | git branch --unset-upstream |
| La første vanlige push sette den (Git 2.37 eller nyere) | git config --global push.autoSetupRemote true |
Ahead og behind beregnes lokalt mot origin/main. Kjør git fetch først når du trenger sannheten om remoten.
Bare repositories
git init --bare lager et repository uten arbeidsmappe: mappen inneholder det som ellers ligger inne i .git. Et delt repository på en server er vanligvis et bare repository, fordi ingen redigerer filer der.
Mer enn én remote
I en fork-arbeidsflyt er origin som regel din egen fork, der du får pushe, og upstream er hovedprosjektet, som du bare leser fra. Du forker prosjektet i hostingtjenesten, kloner forken som origin, pusher brancher dit og åpner pull requesten fra forken mot originalen:
git remote add upstream https://example.org/project/project.git
git fetch upstream
git switch -c fix-typo upstream/main
Per-Arne's Git Good!