Lokal guide til Git

Dette dokumentet beskriver UiOs Git-tjeneste. Det er ogs? en introduksjon til bruk av Git, samt litt generell informasjon om Git-kommandoer.

1???Om Git

Git er et distribuert revisjonskontrollsystem med fokus p? hastighet. Git var i begynnelsen designet og uviklet av Linus Torvalds for ? holde orden p? utvikling av Linux-kjernen, men har siden blitt utviklet videre til ? bli et sv?rt kraftig verkt?y brukt i sv?rt mange store prosjekter.

Hvert arbeidstre i Git er et fullt repository med all historikk og full sporing av revisjoner. Man er ikke avhengig av nettverk eller en sentral tjeneste. Git er fri programvare under GPLv2.

1.1???Hvorfor git?

Git er for tiden (2012) det mest popul?re systemet for revisjonskontroll, ihvertfall innen fri programvare. Git har flere kararteristikker som er sv?rt tiltalende. Her er de viktigste:

God st?tte for ikke-linj?r utvikling
Git st?tter enkelt ? raskt lage nye grener i utviklingen (branching) og sammensmelting av grener (merging). Git har spesielle verkt?y for ? visualisere og navigere en ikke-linj?r utviklingshistorikk. En gren (branch) i Git er sv?rt lettvekt, den er kun en referanse til en enkelt commit. Hele grenstrukturen kan bli konstruert ved ? se bakover p? slike referanser.
Distribuert utvikling
Som endel andre tilsvarende verkt?y for versjonskontroll (men ulikt Subversion og CVS), gir Git hver utvikler en lokal kopi av hele utviklingshistorikken. Endringer kan kopieres fra ett slikt repository til et annet. Disse endringene importeres som ekstra grener (branches), og kan smeltes sammen (merges) p? samme m?te som en lokalt utviklet gren (branch).
Kompabilitet med eksisterende systemer og protokoller
Repositories kan bli publisert via kjente protokoller som HTTP, FTP og rsync. I tillegg finnes det en egen Git-protokoll som enten kan brukes over en vanlig socket eller via ssh. Git har ogs? st?tte for ? kunne brukes sammen med Subversion eller CVS.
Effektiv behandling av store prosjekter
Git har et sv?rt godt rykte for ? v?re effektiv og rask, ogs? n?r det handler om store prosjekter med sv?rt mange filer og komplisert utviklingshistorikk. Git blir ikke tregere etter hvert som historikken blir st?rre.
Kryptografisk autentisering av historikk
Git-historikken lagres p? en slik m?te at navnet p? en revisjon (dvs. en commit) avhenger av den komplette historikken som leder opp til denne enkelte commit'en. N?r historikken er publisert, er det teoretisk umulig ? endre eldre versjoner uten at det kan bli lagt merke til.

2???UiOs Git-tjeneste

Git er et distribuert system for versjonskontroll, slik at det ikke er n?dvendig med en sentral server. I endel tilfeller er det likevel ?nskelig ? bruke en sentral server som "upstream", alts? en autoritativ kilde som gir de riktige tilganger.

UiOs Git-tjeneste best?r av en enkelt tjenermaskin med navn git-prod01.uio.no og alias git.uio.no. Den er satt opp med programvaren Gitolite, som gir oss sv?rt finmasket tilgangskontroll til hvert Git-repository. Kommunikasjon med den sentrale tjenermaskinen fungerer via ssh, mer spesifikt via ssh-n?kler. Enhver som skal ha tilgang til et repository (annet enn anonym tilgang) m? bruke denne mekanismen.

Anonym tilgang for et prosjekt kan gis dersom det er ?nskelig. Dette betyr at prosjektet med full historikk er tilgjengelig for hele verden via Gitweb og/eller Git-protokollen. Det gis ikke under noen omstendigheter anonym skrivetilgang, kun lesing. Om man ?nsker anonym tilgang til prosjektet m? angis ved bestilling, men det er selvsagt mulig ? skru av og p? dette i etterkant.

3???Forberedelser

3.1???Bestilling

For ? bestille et nytt Git-repository m? man sende en e-post til unix-drift@usit.uio.no med f?lgende informasjon:

  • Navn p? git-repository. Dette skal best? av kun sm? bokstaver, tall og spesialtegn - og _. Navn b?r inneholde avdeling, f.eks.: "usit-foo", "ifi-bar".
  • Kort beskrivelse av repo, brukes til Gitweb og/eller utsending av mail om endringer (push) til repoet.
  • UiO-brukernavn til ansvarlig eier.
  • Hvem andre som skal ha tilgang (UiO-brukernavn). Dersom det skal gis tilgang til personer utenfor UiO: Fullt navn. Hvis noen skal ha kun lesetilgang eller tilgang skal styres p? branch-niv? m? dette spesifiseres.
  • Offentlig SSH-n?kkel til de som skal ha tilgang, dersom n?kkel ikke ligger inne fra f?r. Se SSH-n?kler for informasjon om dette
  • Skal repoet v?re tilgjengelig for hele verden via web og git-protokollen?
  • Dersom det er ?nskelig med e-post om hver push til repoet, hvilken e-postadresse dette skal sendes til.

3.2???SSH-n?kler

Vi bruker SSH-n?kler for ? gi tilgang til git-repoet. Slik gj?r du for ? lage et n?kkelpar p? en Linux-maskin:

  1. Hvis du ikke har en RSA-n?kkel fra f?r, lag en ny slik:

    ssh-keygen -t rsa -b 4096
    
  2. Send ~/.ssh/id_rsa.pub til unix-drift@usit.uio.no sammen med bestillingen. Vi trenger ogs? SSH-n?kkel for andre brukere som skal ha tilgang. Kall dem gjerne <brukernavn>.pub.

Vi vil legge inn n?kkelen i systemet og gi deg tilgang til det som du skal ha tilgang til.

Ved endring av tilgang til repoet, kontakt unix-drift@usit.uio.no, vi kan erstatte eksisterende SSH-n?kler, legge til for nye brukere eller slette. Kun den registrerte eieren av et repo kan be om endring av tilganger.

3.3???Sette opp config for git

Git forventer ? finne en fil ~/.gitconfig som minst inneholder f?lgende:

[user]
        name = <ditt navn>
        email = <din e-postadresse>

Denne kan enten lages manuelt, eller man kan bruke git config, slik:

git config --global user.name '<ditt navn>'
git config --global user.email '<din e-postadresse>'

Se for ?vrig git-config(1).

4???Komme i gang

I den videre teksten refereres det til git-repoet mittrepo. Bytt ut dette navnet med det egentlige navnet p? repoet.

Hent ned en lokal kopi av mittrepo:

$ git clone gitolite@git.uio.no:mittrepo
Initialized empty Git repository in /usit/platon/bsd-u1/trondham/git/mittrepo/.git/
warning: You appear to have cloned an empty repository.

N? er katalogen mittrepo laget, og denne katalogen vil v?re tom siden det ikke lagt inn noe innhold forel?pig.

N? kan du begynne ? dytte inn innhold, la oss si at vi lager en fil til ? begynne med, kalt minfil.txt. F?rst legge den til:

$ git add minfil.txt

Deretter commit:

$ git commit -m 'Initial commit'
[master (root-commit) 1a2dcd1] initial commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 minfil.txt

Push endringene til remote:

$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 3.38 KiB, done.
Total 6 (delta 0), reused 0 (delta 0)
To gitolite@git.uio.no:mittrepo
 * [new branch]      master -> master

Videre kan vi bruke git push uten ? spesifisere hvordan ting skal merges.

5???Enkel bruk av git

Her forutsettes det at aktiv katalog er mittrepo.

5.1???Legge til en fil lokalt

For ? legge til en fil:

git add <filnavn>

Filen m? eksistere fra f?r.

Se for ?vrig git-add(1).

5.2???Sjekke inn endringer lokalt

For ? sjekke inn endringer:

git add [filer...]
git commit [filer...]

Hvis man ikke vil kontrollere hvilke filer det gjelder trenger man ikke spesifisere filer. Da vil git s?ke gjennom hele katalogen for ? finne ut hva som er endret. Det vil komme opp en editor der man skal skrive commit-melding. Man kan isteden angi denne p? kommandolinjen:

git commit -m '<melding>' [filer...]

Man kan ogs? velge ? gj?re "add" i samme prosess, dvs. at man slipper ? gj?re en egen "git add", men kun hvis filen finnes i git fra f?r:

git commit -a [filer...]

Ting kan kombineres:

git commit -a -m '<melding>' [filer...]

Se for ?vrig git-commit(1).

5.3???Pushe endringer til sentralt repo

En "git commit" vil kun sjekke inn endringer lokalt, i ditt lokale repository. For ? f? dette inn p? git-serveren m? man bruke push:

git push

Se for ?vrig git-push(1).

5.4???Hent endringer fra sentralt repo

Man kan oppdatere sitt lokale repo fra det sentrale ved ? bruke pull:

git pull

Se for ?vrig git-pull(1).

6???Overgang fra Subversion

Det er mulig ? overf?re et subversion-arkiv til Git og ta med all historikk fra Subversion i prosessen. Det forutsettes at dette skal inn i et nylig opprettet og tomt Git-repository. Videre gj?res dette p? f?lgende m?te:

  1. Installer rpm-pakken git-svn (som root):

    $ sudo yum install git-svn
    
  2. Bruk git-svn til ? klone ut fra Subversion og omgj?re til et lokalt Git-repository:

    $ git svn clone svn+ssh://vcs-usit.uio.no/svnroot/eksempel/trunk/mittrepo
    [...]
    Checked out HEAD:
       svn+ssh://vcs-usit.uio.no/svnroot/eksempel/trunk/mittrepo r22220
    
  3. Katalogen for repoet opprettes i prosessen, cd til denne:

    $ cd mittrepo
    
  4. Legg til ny upstream for repoet:

    $ git remote add origin ssh://gitolite@git.uio.no/mittrepo
    
  5. Dytt det lokale repoet upstream:

    $ git push -u origin master
    Counting objects: 1506, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (1502/1502), done.
    Writing objects: 100% (1506/1506), 329.91 KiB, done.
    Total 1506 (delta 1377), reused 0 (delta 0)
    To ssh://gitolite@git.uio.no/mittrepo
     * [new branch]      master -> master
    Branch master set up to track remote branch master from origin.
    

    Opsjonen -u s?rger for at ny default upstream settes.

N?r dette er gjort kan git-repoet brukes p? vanlig m?te.

7???Enkel bruk av branching

Den normale m?ten ? utvikle p? med Subversion og CVS er noe slikt som dette:

Linj?r utviklingsmodell

Git sin commit-historikk er mer kompleks enn det man finner i Subversion, CVS og tilsvarende systemer. I Git kan en commit ha flere foreldre og flere barn (rettet asyklisk graf). Dette betyr at man ikke er n?dt til ? redigere p? siste revisjon av koden. Man kan lage en commit basert p? en hvilken som helst commit og lage en gren av den. N?r man s? ?nsker ? smelte disse sammen (merge), lager man en commit som er et barn av to commits. Slike barn kalles "merge commits".

Den vanligste m?ten ? bruke branching er til eksperimentelle features i et prosjekt, ev. til back-porting av endringer til en stabil branch.

Ettersom branching i Git er s?pass effektivt og enkelt er det naturlig ? f?lge en utviklingsmodell som ser slik ut:

Grenet utviklingsmodell

For ? se hvilke grener som er tilgjengelig, og hvilken som er aktiv (angitt med stjerne "*"):

$ git branch
* master

For ? lage en ny branch:

$ git branch test

$ git branch
* master
  test

For ? endre aktiv branch:

$ git checkout test
Switched to branch 'test'

$ git branch
  master
* test

Man kan ogs? ta en snarvei og spesifisere ny branch ved checkout:

$ git checkout -b test2
Switched to a new branch 'test2'

$ git branch
  master
  test
* test2

7.1???Merging

Dersom man er forn?yd med endringene som er utf?rt i en branch, kan man gj?re merge av denne inn til en annen, f.eks. fra en test-branch til en prod-branch. I eksemplet gj?r vi merge av innholdet i test inn i master:

  1. S?rg for at aktiv branch er den som det skal merges inn i:

    $ git checkout master
    Switched to branch 'master'
    
  2. Kj?r git merge:

    $ git merge test
    Updating bdebdfc..10c644c
    Fast-forward
     minfil.txt |    1 +
     1 files changed, 1 insertions(+), 0 deletions(-)
    

    Dersom du f?r en konflikt ser det slik ut:

    Auto-merging minfil.txt
    CONFLICT (content): Merge conflict in minfil.txt
    Automatic merge failed; fix conflicts and then commit the result.
    

    Ev. konflikter m? l?ses f?r en merge kan fullf?res.

  3. Til slutt gj?res commit:

    $ git commit -a -m 'melding'
    [el6 5ad8e86] melding
    

For mer informasjon, se git-merge(1).

7.2???Slette en branch

Dette gj?res slik:

$ git branch -d test
Deleted branch test (was 8f08040).

Dette forutsetter at man har gjort git merge f?rst. Dersom endringene i 'test' skal kastes uten videre, bruk git branch -D test.

For mer informasjon, se git-branch(1).

8???Tips og triks

8.1???Farger i diff og annen output

For ? f? farger fra git diff og andre Git-kommandoer kan man sette f?lgende i ~/.gitconfig:

[color]
        ui = auto

Dette kan ogs? settes vha. git config:

git config --global color.ui auto

8.2???Aliaser til Git-kommandoer

Man kan sette aliaser for Git-kommandoer p? denne m?ten:

[alias]
        <alias> = <kommando>

Eksempel:

[alias]
        co = checkout

Dette kan ogs? settes med git config (eksempel):

git config --global alias.co checkout

8.3???Bruke meld som verkt?y for merging

Meld er et GUI-program (GNOME) for ? visualisere og hjelpe med merging. Dersom man ?nsker at Git i tilfelle konflikt ved merge skal starte Meld automatisk, kan man sette i ~/.gitconfig:

[merge]
        tool = meld

Eller med git config:

git config --global merge.tool meld

Husk ? ogs? installere Meld:

sudo yum -y install meld

8.4???Vise aktiv branch i prompt

For ? f? bash til ? vise aktiv branch i prompet kan man sette PS1 p? f?lgende m?te i ~/.bashrc:

if [ -f /etc/bash_completion.d/git ]; then
    source /etc/bash_completion.d/git
    export GIT_PS1_SHOWDIRTYSTATE=true
    export GIT_PS1_SHOWUNTRACKEDFILES=true
fi
export PS1='[\u@\h \W$(declare -F __git_ps1 &>/dev/null && __git_ps1 " (%s)")]\$ '

Dette vil s?rge for at bash-prompten ser slik ut:

[user@host directory-name (master)]$

I tillegg til ? vise hvilken branch man jobber p?, vil dette ogs? vise om men er i en merge eller rebase:

[user@host directory-name (master*)]$
[user@host directory-name (master+)]$
[user@host directory-name (master%)]$
  • P? den f?rste linjen er en fil endret
  • P? den andre linjen er en fil endret og man har gjort git add men ikke git commit
  • P? den tredje linjen er det laget en ny fil som ikke er i git

Disse vil naturligvis kombineres.

9???For administrator av git-tjenesten

Administrasjon av git-repoer gj?res p? samme m?te som med koji-git, ved hjelp av gitolite. Forskjellen er at man endrer gitolite@git.uio.no:gitolite-admin for ? administrere det generelle git-repoet.

Notat

Personlige/private repoer skal prefikses med private. Ved prosjekt-repoer: Sjekk ogs? om det bestilte navnet har potensiale for fremtidig navnekollisjon og bruk n?dvendige prefikser for ? redusere faren for dette. Bruk ekisterende repo-navn som retningslinje i den grad der er mulig.

Av Trond Hasle Amundsen
Publisert 13. mai 2013 16:00