Praktisk livredning med git Miniseminar NTNU, 22. september 2011 Åsmund Eldhuset
Hvem kjenner seg igjen her? Hvor mange kjenner seg igjen?
Hvorfor? Hvor mange har samarbeidet om koding/dokumentskriving og løst det ved å... Kreve at alle må være fysisk til stede og samarbeide om det samme fysiske dokumentet Ha et delt dokument og kreve at bare én jobber av gangen Ha et delt dokument som man kopierer hver gang man skal jobbe med det, eller ett dokument per person, og én person som har som jobb å lime sammen alle endringer Hvor mange har backups av formen Versjon1.doc, Versjon1.5.doc, Versjon2.doc, Versjon2_korrigert.doc, Versjon_2011-04-08.doc, Versjon09042011.doc, Versjon2_slettes.doc, ...? (Hvis noen har brukt Dropbox, er det et godt stykke bedre, men git er et enda bedre alternativ, så lenge man jobber med ren tekst)
Hva er et versjonskontrollsystem? Et system for å holde styring på... Programkode HTML og CSS LaTeX-dokumenter Hva som helst som er ren tekst Vedlikeholder en fullstendig historikk over alle endringer Kan spole tilbake til en tidligere tilstand Kan vise hvem som har gjort endringer Kan la folk jobbe på de samme filene samtidig uten å forstyrre hverandre Endringene slås automatisk sammen etterpå
Git vs. andre versjonskontrollsystemer Versjonskontrollsystemer kan være... Sentraliserte SVN, CVS, TFS, ... Historikken finnes på en sentral server; nesten alle operasjoner går mot denne Distribuerte Git, Mercurial, Bazaar, ... Hele historikken finnes lokalt; fleste operasjoner gjøres lokalt Kan likevel samarbeide via en sentralisert server Distribuerte systemer er generelt sett mer fleksible Git er ekstremt kraftig, men... Brattere læringskurve Litt lettere å skyte seg selv i foten Mercurial (Hg) ligner på git, men er lettere (se hginit.com)
Installasjon Anbefaler MSYSGit med GitExtensions Litt knot på Windows, men går stort sett bra Må sette opp PuTTY, PuTTYgen og Pageant hvis du skal jobbe mot en server
git config git config --global user.name "Aasmund Eldhuset" git config --global user.email aasmund.eldhuset@bekk.no Kan gi problemer hvis Windows-brukernavnet ditt inneholder norske bokstaver (men det funker fra GitExtensions sitt config-vindu) Dropp --global og konfigurer per repository i stedet
git init – get it going! Lager et nytt repository i mappen du står i Et repository inneholder den magiske .git-mappen; ikke rør innholdet her Unntatt .git/config hvis du føler deg barsk Repositoryet er en slags database som inneholder historikken til alle filene Alt utenfor .git kalles for working directory; inneholder den nåværende tilstanden til alle filene dine Det finnes mange operasjoner for å sammenligne working directory med repository git init --bare lager et repository, men ingen working directory (bra å bruke dette på servere)
git status Viser forskjellen mellom working directory og siste commit i repositoryet
git diff Viser hvordan innholdet i filene i working directory er forskjellig fra den siste committen
git add Registrerer nye eller endrede filer i staging area / index, som er et område man bruker til å forberede en commit git diff --cached viser hvilke endringer som ligger i staging area Det går også an å registrere bare deler av en fil: git add -p filename
git commit Registrerer alle de stagede endringene som én commit / revision Du må også oppgi en beskrivende commitmelding: git commit –m "Message" Dato, tidspunkt og hvem du er registreres automatisk Committen får en id, som er en hashkode som er basert på innholdet i committen, f.eks. a5760810e2766e4b0ab6791ca53d44d0d1e499d7. Denne må senere brukes hvis man skal referere til committen. Det holder heldigvis å bruke et prefiks, f.eks. a5760. Grunnen til at committene ikke nummereres på "normal" måte er at historikken ikke nødvendigvis er lineær – mer om dette senere Commit ofte! En commit er et checkpoint som du når som helst kan gå tilbake til når du har rotet til ting Det er heller ikke nødvendig å ha noe som fungerer for at du skal kunne committe (selv om det er det optimale) git commit -a (amend) kan fikse på den siste committen (legge til/fjerne/modifisere ting, og modifisere commitmeldingen). Ikke gjør dette hvis du allerede har pushet commiten! (Mer om pushing senere.)
Hva ligger i repositoryet? Working directory hello.txt +Hello world! +It's a lovely day. -Hello world! +Hello there! 21.09.2011 18:23:48 – Åsmund Eldhuset 21.09.2011 19:15:01 – Anders Hammervold 21.09.2011 20:18:24 – Jonas Follesø +Enjoy it! 22.09.2011 01:29:18 – Åsmund Eldhuset hello.py +print "Hello world!" hello.txt Hello there! It's a lovely day. Enjoy it! hello.py print "Hello world!"
git log Viser endringsloggen (sekvensen av commits)
git show Viser hvilke endringer en commit inneholder
.gitignore Filnavn, mappenavn og patterns som står i filen .gitignore vil ignoreres av git status .gitignore i seg selv må committes
Git Extensions git log er litt strevsom å lese, særlig når historikken blir lang Mye bedre med grafiske verktøy
git checkout Å sjekke ut en commit vil gjøre at hele innholdet i working directory endrer seg til å gjenspeile tilstanden ved den committen – altså er det som om at man går tilbake i tid Men endringene du gjorde etter committen du sjekket ut ligger fortsatt bevart, og du kan sjekke dem ut for å komme tilbake dit Det holder å bruke et prefiks av commit-hashen git checkout ab391c
git reset git reset --hard nullstiller endringene i working directory slik at du kommer tilbake til tilstanden i den siste committen Kan ikke angres!
git branch En branch er en slags etikett som er klistret på en commit En branch kan dessuten sjekkes ut Dette vil sjekke ut committen branchen peker på I tillegg vil selve branchen få status som "den utsjekkede branchen" Til enhver tid er én eller ingen brancher sjekket ut (hvis du sjekker ut en commit direkte, vil ingen brancher være sjekket ut) Hvis du har sjekket ut en branch, vil branchen flytte seg fremover automatisk når du committer I tillegg finnes en "usynlig" branch som heter HEAD, og som alltid peker på den committen du står på
git branch og git checkout git branch branchname lager en branch der du står nå, men uten å sjekke den ut git branch branchname commit lager en branch på den oppgitte committen git checkout branchname sjekker ut en branch git checkout -b branchname lager en branch der du står nå og sjekker den ut git checkout commit/branchname -- filename setter en fil tilbake i den tilstanden den var i den aktuelle branchen/committen
git merge Du kan sjekke ut en commit som har etterfølgende commits, og så gjøre en ny commit. Da vil du skape to forskjellige stier i historikken (dette er det som tradisjonelt sett har blitt refert til som en "branch" i andre versjonskontrollsystemer) Ekstremt nyttig Flere personer kan utvikle forskjellige ting samtidig uten å forstyrre hverandre med halvferdig kode Én person kan utvikle forskjellige ting samtidig, og hoppe mellom de forskjellige branchene uten å bli forstyrret git merge otherbranch
git merge
git clone Kopierer et repository fra en annen server og registrerer server- repositoryet som en remote Gjøres som regel over SSH Må ha PuTTY installert Bør bruke PuTTYgen og Pageant til å forenkle innloggingen
git fetch git fetch remotename Laster ned nye commits fra remote, men bare fra de branchene du tracker Bruk git fetch remotename branchname:branchname for å laste ned en branch du ikke har
git fetch Local Remote
git push og git pull git push remotename branchname laster opp dine nye commits fra den angitte branchen til det angitte repositoryet Dette får du bare lov til dersom ikke noen andre allerede har gjort nye commits på den samme branchen git pull remotename branchname gjør først en git fetch remotename og så en git merge branchname
git pull (egen branch) Local Remote
git pull (annen branch) Local Remote
Vanlige tabber Sjekke ut en commit (ikke via en branch), gjøre nye commits, å så sjekke ut noe annet De nye committene vil tilsynelatende forsvinne fordi de ikke hadde noen branch knyttet til seg Løsning Hvis du oppdager dette før committen, lag enten en ny branch med git checkout -b newbranch, eller flytt en eksisterende branch dit du er med git branch -f oldbranch Hvis ikke, bruk git reflog for å finne den "tapte" committen i "søppelbøtten" til git. Gjør git branch newbranch commit eller git branch -f oldbranch commit, og så git checkout newbranch eller git checkout oldbranch
github – fork me, baby! Populær nettside som hoster git-repos for open source-prosjekter gratis Kjekt hvis man skal samarbeide om et prosjekt Kan også betale for å få private repos (vi bruker dette i BEKK) Kan også fork'e andres prosjekter, gjøre forbedringer og sende committene tilbake
Konsulent, Avdeling Trondheim Åsmund Eldhuset Konsulent, Avdeling Trondheim 959 39 826 aasmund.eldhuset@bekk.no