Er du en av dem som skuler litt misunnelig på de kule gutta med friprog-prosjekter på GitHub?
De som brancher og forker og merger i ett sett. De som skryter av at de sitter på flyet og commiter mens de er offline.
Mens du er stuck med subversion som bare fungerer når du er på nett og som er klar til å bite deg bare du tenker på å lage en aldri så liten branch.

Med git-svn kan du ha så mange lokale git-branch’er du vil. Hoppe frem og tilbake, slå sammen alle de små commitene du gjorde mens du satt på t-banen og hente frem den ene lille endringen du gjorde i en eksperimentell branch i forrige uke (vha. funksjonen med det velklingende navnet cherry-pick). Jeg skal ikke misjonere mere for gits kvaliteter i denne posten, det er beskrevet veldig mye bedre enn det jeg klarer på bl.a. disse nettstedene:
Clone
For å komme i gang trenger man bare å kjøre denne kommandoen:
$ git svn clone <subversion-url> ?optional-directory-name?
Smør deg med tålmodighet, for den laster ned hele svns commit-historie. Det finnes ekstra options for å laste ned alle eksisterende branch’er og tags også. Nå har du en git-klone av svn-repoet.
Rebase
Når man bruker svn update hentes eventuelle endringer ned fra det sentrale repo’et og disse merges sammen med din lokale kopi.
git svn rebase prøver å etterligne det update gjør og da kan det se sånn ut:
$ git svn rebase
M Makefile
r3 = ae409c2f5fe0831f22d6dc891652b5f9159f35de (git-svn)
First, rewinding head to replay your work on top of it…
Applying: Local git commit.
På linje 4 ser du at det står noe om rewinding og replay your work on top of it . Dette er noe git-svn må gjøre fordi svn ikke har noe konsept om lokale commits, noe git selv har. For at ting ikke skal krølle seg når man skal commite tilbake til svn må man først rulle tilbake alle de lokale git-commitene, hente ned endringene som finnes i svn og så legge de lokale commitene på toppen av disse igjen. Historien stokkes litt om på, men det er nødvendig for at svn skal henge med på det som skjer.
Når du har kjørt git svn rebase er du klar til å commite dine lokale endringer tilbake til svn repo’et med kommandoen git svn dcommit.
Det er viktig å huske på at en del av det som lett kan gjøres i git ikke fungerer i det hele tatt i svn. Derfor bør man følge disse reglene:
- Ikke dcommit endringer som er en følge av en merge til subversion. Svn håndterer merge-opperasjoner på en annen måte enn git og derfor må man holde git-historien linjær (ingen merging fra andre brancher, bare rebasing).
- Aldri gjør endringer (amend, squash, sletting) på commits som er dcommitet til svn. Samme regel gjelder forøvrig for git-commits som er lagt ut i et offentlig repo.
Workflow
#
# HACK
#
CURRENT=`git branch | grep ‘\*’ | awk ‘{print $2}’`
status=`git checkout master | awk ‘{print $1}’`
if [[ ! "${status}" =~ error ]]; then
git svn rebase
git checkout ${CURRENT}
git rebase master
fi
Det som skjer her er:
- Topic-branchens navn lagres i CURRENT
- Forsøker å bytte over til master-branchen og sjekker at det går bra.
- Henter oppdateringer fra svn repoet med svn rebase.
- Bytter tilbake til CURRENT og kjører rebase mot master
Dette scriptet kjøres for å holde topic-branchen oppdatert med både master-branchen og svn-repo.
Når oppgaven er utført og jeg skal sjekke inn alle endringene bruker jeg ship-scriptet.
#!/bin/bash
#
# SHIP
#
CURRENT=`git branch | grep ‘\*’ | awk ‘{print $2}’`
git rebase -i master
status=`git checkout master | awk ‘{print $1}’`
if [[ ! "${status}" =~ error ]]; then
git merge ${CURRENT}
git svn dcommit
git checkout ${CURRENT}
fi
Her gjør vi det motsatte av i hack:
- Interactive rebase (-i) gjør det mulig å slå sammen (squash) alle små commits gjort underveis i utviklinga
- Endringene merges over i master-branchen. (den observante leser vil se at dette strider mot regel 1. over, men pga. den første rebasen går det bra)
- Alt commites til svn og man er tilbake i topic-branchen
- Man kan nå fortsette utviklingnen i topic-branchen eller gå tilbake i master, slette topic-branchen og man har blanke ark til å starte på neste oppgave
Et steg i riktig retning
Det var det, ingen grunn til å la seg sinke av svn når man kan kjøre med en slik hybridløsning. Etterhvert kan du kanskje overbevise hele teamet, og produkteier, om gits fortreffelighet og bruke det som et ekte distribuert versjonkontrollsystem. Inntil du klarer dette kan du nå enkelt bruke topic-branches, lage hotfix-patcher og spore endringer (og hvem som gjorde dem) ned på linjenivå.