' TDDD63 > Subversion
Hide menu

Subversion i TDDD63

Kort om versionshantering

Varför versionshantering?

Versionshantering är ett sätt att spara ändringshistorik för ett projekt, d.v.s. hur de filer som projektet är uppbyggt av förändrats med tiden. Det låter kanske trist, och det kan kännas onödigt när man bara är några personer som jobbar på ett projekt under en kort tid. Men att regelbundet checka in ändringar när du implementerar nya finesser och fixar buggar kan spara mycket tid och besvär i längden. Börja nu!

  • Systemet håller reda på vad som har ändrats, när, och av vem.

  • Jobbigt att eposta uppdateringar fram och tillbaka? Svårt att hålla reda på vilken version av projektet som är den nyaste? Med versionshantering kan du lätt hämta och infoga de senaste ändringarna som har checkats in av andra projektmedlemmar med ett enkelt kommando.

  • Behöver assistenten kolla en eller flera versioner av din kod? Skicka ett revisionsnummer (versionsnummer), istället för att eposta hela koden.

  • Har du infört nya buggar och önskar att du hade gjort en kopia av koden innan? Med versionshantering kan du återgå till vilken gammal version som helst, utan att manuellt kopiera versioner till separata kataloger som "project", "project-old", och "project-really-the-newest". Alla versioner är märkta med datum och loggmeddelande så du vet vad som är vad.

  • Minns du inte vad du gjorde sedan förra statusrapporten? Fråga versionshanteringssystemet.

  • ...och så vidare.

Subversion

Det versionhanteringsystem som används av IDA, och som ni kommer att använda er av i denna kurs, heter Subversion (SVN). Det är ett open source-projekt och är väldigt utbrett bland open source-användare. Exempel på grupper som använder det är Apache, Google Code och Source Forge.

Som de flesta versionshanteringssystem baseras Subversion på att alla versioner av alla filer som ingår i ett projekt lagras i ett filarkiv, även kallat repository eller kortare repo. Filarkivet implementeras som en sorts databas. Ofta hanteras denna databas av en server som är åtkomlig via Internet.

Man har sedan en separat kopia av den nuvarande versionen av projektets filer i en egen katalog, en arbetskopia, där man gör alla sina ändringar. I en arbetskopia finns bara en version av filerna, den "nuvarande".

När man har klarat av ett delmoment (eller jobbat färdigt för dagen) uppdaterar man filarkivet med de ändringar man just har gjort: svn commit. När nästa person sedan ska arbeta med projektet (eller man ska börja arbeta från en annan dator som har sin egen arbetskopia) börjar man med att infoga de senaste uppdateringarna från filarkivet: svn update.

Om ni inte redan är vana vid versionshantering rekommenderar vi starkt att ni läser denna visuella introduktion, speciellt avsnittet "Visual Examples". Det kommer att underlätta arbetet i den här kursen och vara användbart i många andra kurser i framtiden.

Att använda Subversion

Kolla om Subversion är installerat

För att kunna använda Subversion på Sun-datorerna måste du ha lagt till rätt modul. Kontrollera om du redan har modulen installerad genom att ge följande kommando i ett terminalfönster:

svn help

Om svaret är "svn: Command not found" eller liknande måste du lägga till Subversion-modulen. Antingen kan du i varje terminalfönster där du vill använda Subversion ge kommandot

module add prog/subversion

eller så kan du ge följande kommando i något terminalfönster

module initadd prog/subversion

och logga ut. Därefter kommer Subversion att automatiskt vara tillgängligt i alla terminalfönster du öppnar.

Kör du på egen dator?

Om du använder dig av en egen dator med Ubuntu eller Debian, kan du installera Subversion med:

sudo apt-get install subversion

På Windows är TortoiseSVN en bra grafisk Subversion-klient. För installation på andra system, se http://subversion.apache.org/

Hur ett repository fungerar

Hur kommer man åt ett repo?

Varje katalog i ett Subversion-repository identifieras av en URL. Har man URLen, plus lösenord till ett konto som har tillgång till katalogen, kan man t.ex. kolla vilka filer som finns eller checka ut den senaste versionen av filerna i katalogen till en arbetskopia. I den här kursen kommer bara gruppens medlemmar och era assistenter att ha tillgång till filerna.

I den här kursen kommer det att skapas en separat katalog för varje grupp centralt på servern "svn-und.ida.liu.se". URLerna kommer att vara på formen https://svn-und.ida.liu.se/courses/TDDD63/2013-1-Project/grupp_maps-10 där "maps" är namnet på en "storgrupp" i WebReg och 10 är ett löpnummer inom "storgruppen". Se listan på kataloger.

För att kontrollera innehållet i en katalog, ge följande kommando:

svn list <your URL>

t.ex.

svn list https://svn-und.ida.liu.se/courses/TDDD63/2013-1-Project/grupp_maps-10

Checka ut från ett repo till en ny arbetskopia

Om du vill delta i ett projekt som använder sig av Subversion (vilket du vill!) behöver du först "checka ut" en egen kopia av projektets senaste version. Du får då en arbetskopia av projektet, en katalogstruktur där du kan göra egna lokala ändringar och tillägg. Du checkar ut en arbetskopia genom att köra kommandot svn checkout <URL to repo> <where you want to store the working copy>

Exempel (notera att det är två argument till checkout, där det andra bara är en punkt – "lagra i den här katalogen"):

user@computer:~/TDDD63$ mkdir maps
user@computer:~/TDDD63$ cd maps
user@computer:~/TDDD63/maps$ svn checkout https://svn-und.ida.liu.se/courses/TDDD63/2013-1-Project/grupp_maps-10 .
Checked out revision 10.

Kör du detta kommando kommer alla filer och kataloger i senaste revisionen av projektet att läggas till i ~/TDDD63/maps. Du får även en underkatalog som heter ".svn" där det lagras filer som Subversion behöver för att veta var alla filer kom ifrån, hur de såg ut när de checkades ut, och så vidare. Den katalogen kan du ignorera – den är viktig men används bara internt av svn-kommandot.

Första gången du gör detta i TDDD63 är katalogen som checkas ut tom. Du måste ändå checka ut enligt beskrivningen ovan för att katalogen ".svn" ska skapas och fyllas med rätt innehåll. Det är på det sättet din katalog (~/TDDD63/maps i exemplet) blir en arbetskopia och inte bara en vanlig katalog.

Den uppmärksamme kanske ser att revisionsnumret för den första utcheckningen inte är 1. Detta beror på att alla grupper i kursen använder samma repository (men olika kataloger inom repositoryt), och revisionsnumret är globalt för ett helt repository. Revisionerna för era incheckningar kommer kanske att bli 251, 287, 319, och så vidare.

Nu är du igång! Det är bara att börja jobba med arbetskopian, lägga till filer, modifiera filer, ta bort filer (med "svn rm" enligt nedan!), döpa om filer (med "svn mv"!), checka in dina ändringar, uppdatera med andras incheckade ändringar, och så vidare.

Referensinformation om checkout...

Hur gör jag för att...

Lägga till en fil

Filer du skapar i mappen där repot ligger kommer inte automatiskt att bli versionshanterade, utan du måste säga till svn att den ska ta hand om de nya filerna. Gör detta med kommandot svn add <file>. Om du kör svn status kommer den att visa ett ? om du inte har lagt till den: Subversion vet inget om den filen. När du har lagt till den kommer den att visa ett A, som betyder "added". Denna fil kommer att läggas till i repot nästa gång du gör en commit.

user@computer:~/TDDD63/maps$ touch shortest_path.py
user@computer:~/TDDD63/maps$ svn status
? shortest_path.py
user@computer:~/TDDD63/maps$ svn add shortest_path.py
A shortest_path.py
user@computer:~/TDDD63/maps$ svn status
A shortest_path.py

Referensinformation om svn add...

Ta bort en fil

För att ta bort en fil använder du svn rm <file> istället för bara rm <file>.

På samma sätt som att lägga till en fil, så kommer inte Subversion att sluta versionshantera en fil om du bara tar bort den normalt. Ta istället bort en fil genom att köra svn rm <file>. Detta tar omedelbart bort filen på din dator, precis som bara "rm file" gör. Dessutom noterar Subversion att filen ska vara borta (den har inte bara råkat försvinna av misstag). När du checkar in kommer Subversion att notera detta i repot. När andra användare checkar ut din revision kommer filen då att tas bort även från deras arbetskopior. Gamla versioner av filen finns så klart alltid kvar i ditt repository och kan åter tas fram genom att man checkar ut en specifik revision!

user@computer:~/TDDD63/maps$ svn rm shortest_path.py
D shortest_path.py
user@computer:~/TDDD63/maps$ svn status
D shortest_path.py

Om du skulle råka ta bort en fil med bara rm <file> kommer Subversion att undra var filen tog vägen. Kör du då svn update kommer den att visa ett ! för att Subversion inte kan hitta filen. För att ta bort den från svn också är det bara att köra det vanliga svn rm <file>, så Subversion vet att den faktiskt ska vara borta.

Referensinformation om svn delete...

Hämta det som min arbetskamrat laddat upp

Kör kommandot svn update. Då kommer alla ändringar som checkats in i repot sedan din senaste "svn update" att infogas i din egen arbetskopia. Det kan vara ändringar som en arbetskamrat har gjort eller ändringar som du själv har gjort på en annan dator.

Denna infogning innebär inte att dina egna filer ersätts av den senaste versionen från repot. Istället tittar Subversion på vilka ändringar som har gjorts (t.ex. att 10 rader har adderats på två olika platser i en fil) och gör sitt bästa för att infoga dessa ändringar på rätt plats i dina egna filer. Om du har egna lokala ändringar som du inte har checkat in ska dessa alltså finnas kvar även efter en "svn update".

Se även informationen om konflikter nedan.

user@computer:~/Desktop/svn_fx$ svn update
U dijkstra.py
Updated to revision 10.

Referensinformation om svn update...

Ladda upp det arbete jag har gjort till repot

Kör kommandot svn commit -m '<ditt loggmeddelande>'
OBS! Det är viktigt att ge en bra beskrivning av vad som ha uppdaterats i denna ändring. Dels vill man senare kunna kolla igenom sökhistoriken om man vill hitta den tidpunkt då något specifikt ändrades, dels vill andra som arbetar med samma projekt veta vad som hade ändrats när de uppdaterar med dina senaste ändringar.

Exempel: Ändrat filen shortest_path.py.

user@computer:~/TDDD63/maps$ vim shortest_path.py
user@computer:~/TDDD63/maps$ svn status
M shortest_path.py
user@computer:~/TDDD63/maps$ svn commit -m 'modified the shortest path function so it is now faster'
Sending shortest_path.py
Transmitting file data .
Committed revision 13.

Exempel: Tagit bort filen dijkstra.py

user@computer:~/TDDD63/maps$ svn commit -m 'removed the dijkstra function since it is no longer sufficient, since we will need to handle negative weights'
Deleting dijkstra.py

Committed revision 10.

Om någon har checkat in ändringar efter att du senast checkade ut får du inte checka in på en gång. Då skulle du ju riskera att skriva över dessa ändringar utan att ens ha sett dem. Istället måste du först uppdatera med "svn update" och därmed infoga de senaste ändringarna från repot. När detta är klart kan du checka in.

Referensinformation om svn commit...

Vad ska jag göra om jag råkar commita något felaktigt?

Man kan inte ta bort en commit som har gjort fel: Det som är lagrat i ett repository tas inte bort. Istället åtgärdar man felet så att arbetskopian blir korrekt (t.ex. genom att återställa en gammal version) och gör sedan en ny commit som då blir den nya och korrekta "nyaste versionen". Givetvis förklarar man då i commit-meddelandet vad man har gjort.

Ahhrgh, Subversion säger att jag har en konflikt! Varför får jag detta och hur löser jag det?

Om man får en konflikt brukar det bero på två saker. Antingen så har man glömt att göra en update och redigerat en föråldrad fil, eller så är det två personer som jobbar med samma fil samtidigt. Om det då har skett två olika ändringar på samma plats är det omöjligt för Subversion att veta hur dessa ska kombineras ihop. Exempel:

  • Person 1 checkar ut revision 22.
  • Person 2 checkar också ut revision 22.
  • Person 2 ändrar "äpple" till "päron" på rad 33 och checkar in revision 23.
  • Person 1 ändrar "äpple" till "apelsin" på rad 33.
  • Person 1 försöker checka in men får veta att den lokala arbetskopian först måste uppdateras.
  • Person 1 gör "svn update" för att få med ändringarna från revision 23.
  • Subversion kan omöjligen veta om det ska stå "päron" eller "apelsin" på rad 33, om båda ska vara med, eller om man kanske ska ha något helt annat där.

Konflikter måste lösas manuellt. Det är viktigt att vara noggrann så att man inte går miste om någon ändring! Nedan följer hur det typiskt ser ut om man har fått en konflikt:

user@computer:~/Desktop/svn_fx$ svn commit -m ''
Sending store.py
svn: Commit failed (details follow):
svn: File '/trunk/store.py' is out of date

Lös detta genom att köra update (som så klart kommer klaga, men ger oss möjlighet att lösa konflikten). När du får en konflikt ska du normalt välja "postpone" (p). Du får då en chans att lösa konflikten efter att "svn update" är klart.

user@computer:~/Desktop/svn_fx$ svn update
Conflict discovered in 'store.py'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: p
C store.py
Updated to revision 23.
Summary of conflicts:
Text conflicts: 1

Om vi kör ls kommer vi se att nya filer har skapats.

user@computer:~/Desktop/svn_fx$ ls
dijkstra.py store.py store.py.mine store.py.r22 store.py.r23
  • store.py.mine innehåller exakt det store.py innehöll i din lokala arbetskopia innan du körde "svn update". Den innehåller alla ändringar du gjorde sedan du checkade ut revision 22.
  • store.py.r23 (till exempel) är den senaste versionen av store.py som hade checkats in, precis som den just nu ser ut i repositoryt.
  • store.py.r22 (till exempel) är den senaste gemensamma föräldern till dessa filer. Detta kan jämföras med .mine och .r23 för att se vad du hade ändrat i din arbetskopia och vad andra hade ändrat i repositoryt.
  • store.py innehåller nu Subversions bästa försök att kombinera dina ändringar med de som redan checkats in.

Om vi öppnar store.py i en texteditor kommer vi se att det på vissa ställen finns en konflikt markerad.

79 def print_edge_set(self):
80  for k, n in self.edges.items():
81 <<<<<<< .mine
82   print("id:" + str(k) + "\tne: " + str(n))
83 =======
84   print("ID:" + str(k))
85 >>>>>>> .r23

Dessa ändringar vad det är som ger upphov till konflikten. Denna fil är en kombination av *.mine och *.rx. Det som står mellan <<<<<<< .mine och ======= är den ändring du själv gjort i den lokala arbetskopian medan det som står mellan ======= och >>>>>>> .r23 är den ändring som är incheckad i repositoryt i revision 23.

För att lösa konflikten ändrar du bara i filen till vad du faktiskt vill ska stå där och tar bort alla <<<<<<< .mine, ======= och >>>>>>> .r23. Det kan betyda att du behöver kombinera kod från båda "avsnitten" eller i vissa fall göra mer omfattande omskrivningar. Spara sedan filen.

79 def print_edge_set(self):
80  for k, n in self.edges.items():
81   print("ID:" + str(k) + "\tne: " + str(n)

Informera sedan svn om att konflikten är löst genom att köra svn resolved <file>. Då kommer alla *.mine och *.rx att försvinna.

user@computer:~/Desktop/svn_fx$ svn resolved store.py
Resolved conflicted state of 'store.py'

Konflikten ska nu vara löst och du ska kunna göra en commit som vanligt.

user@computer:~/Desktop/svn_fx$ svn commit -m '...'
Sending store.py
Transmitting file data .
Committed revision 24.

Om du vill veta mer om hur man kan lösa konflikter, kan du kolla in den officiella dokumentationen här
Ännu en bra länk om att lösa konflikter finns här

Hämta en gammal revision av repot

Anta att du skrivit kod som fungerar och efter det arbetar vidare ytterligare men märker efter ett tag att det blivit någon bugg, efter att du gjort några commits, och du vill gå tillbaka till en tidigare revision. Då kan du köra kommandot svn update -rxxxx, där xxxx står för vilken revision som du vill ha tillbaka. Detta kommando kommer att återskapa din lokala mapp så som den såg ut vid just den revisionen. Den kommer alltså att ta bort de filer som inte fanns vid den revisionen, modifiera tillbaka de filer som ändrats till hur de såg ut vid den revisionen och lägga till de filer som fanns då men nu är borttagna. Notera att detta bara sker i din hemmamapp och ingenting kommer att hända i repot förän du gör en commit. Kanske vill du inte återställa repot till hur den såg ut några revisioner tidigare utan bara hämta innehållet i filer så som de såg ut då och sedan gå tillbaka till den nyaste revisionen.

I exemplet som följer nedan går vi tillbaka till revision 20, genom att köra svn update -r20. Då uppdateras i det här fallet filen store.py till hur den såg ut vid den revisionen. Antingen kan vi göra en commit nu för att gå tillbaka helt till hur repot såg ut vid revision 20 eller så kan vi öppna filen och hämta vad vi vill ha för att sedan gå tillbaka till den nuvarande revisionen genom att göra svn update.

user@computer:~/TDDD63/maps$ svn update -r20
U store.py
Updated to revision 20.
user@computer:~/TDDD63/maps$ svn update
U store.py
Updated to revision 24.

Du kan så klart också göra detta för enskilda filer eller kataloger.

user@computer:~/TDDD63/maps$ svn update -r20 store.py
U store.py
Updated to revision 20.

Mer info...

Återställ en eller flera filer till hur de såg ut vid senaste update

Om du har gjort ändringar du vill återställa, men inte har hunnit checka in dem än, kan du använda svn revert <file> för att återställa specifika filer eller svn revert --depth=infinity <filepath> för att återställa en hel lokal mapp med alla underkataloger och filer. VARNING! detta kommando kommer radera alla ändringar som gjorts sedan senaste updaten, i den givna filen eller i hela mappen om det andra alternativet givits, utan möjlighet att ångra.

Exempel på återställning av fil:

user@computer:~/TDDD63/maps$ svn revert store.py
Reverted 'store.py'

Exempel på återställning av hela den lokala mappen:

user@computer:~/TDDD63/maps$ svn revert --depth=infinity .
Reverted 'dijkstra.py'
Reverted 'store.py'

Mer info...

Kolla vilka filer som har ändrats

Kör kommandot svn status. Nedan följer ett exempel på hur det kan se ut.

user@computer:~/TDDD63/maps$ vim a.py
user@computer:~/TDDD63/maps$ svn rm shortest_path.py
user@computer:~/TDDD63/maps$ touch draw_node.py
user@computer:~/TDDD63/maps$ svn status
? draw_node.py
M graph.py
D shortest_path.py
user@computer:~/TDDD63/maps$

Mer info...

Visa alla filer i repot

Kör kommandot svn list
user@computer:~/TDDD63/maps$ svn list
graph.py
c.py
svn: 'draw_node.py' is not under version control

Här kan man se vilka filer som finns och även se att filen draw_node.py inte är versionshanterad.

Mer info...

Andra Subversion-kommandon

För att se ändringshistoriken (commit-historiken):

svn up
svn log

Mer info...

För att se alla ändringar sedan revision rev:

svn diff -x -wup -r rev

Mer info...

Information om vad du kan göra med Subversion och vilka kommandon som finns:

svn help

Information om ett visst subkommando, subkommando, får du med ett kommando på formen:

svn help subkommando

Mer info...

Det finns, som delvis framgått av exempel ovan, många flaggor till subkommandona.

Mer om Subversion

För mer information om Subversion, se

Länktips:


Page responsible: Patrick Doherty
Last updated: 2013-10-08