På dette punktet skal du ha fått forståelsen av hvordan hver innlegging oppretter et helt nytt filsystemtre (kalt en “revisjon”) i depotet. Hvis ikke, gå tilbake og les om revisjoner i “Revisjoner”.
I dette kapittelet skal vi gå tilbake til det samme eksempelet
fra Kapittel 1, Grunnleggende konsepter.
Du husker at du og din kollega Sally deler et depot som inneholder
to prosjekter – paint og
calc.
Merk imidlertid at i Figur 4.2, “Depotets utseende til å begynne med”
inneholder hver prosjektkatalog underkataloger kalt
trunk og branches.
Grunnen til dette vil du snart få greie på.
Som tidligere, tenk deg at du og Sally begge har arbeidskopier
av “calc”-prosjektet.
Mer spesifikt, dere har begge en arbeidskopi av
/calc/trunk.
Alle filene for prosjektet er i denne underkatalogen istedenfor i
selve /calc, fordi teamet ditt har bestemt at
/calc/trunk er der “hovedlinjen”
av utviklingen skal foregå.
La oss si at du har fått oppgaven å utføre en radikal
reorganisering av prosjektet.
Det vil ta lang tid å skrive, og vil påvirke alle filene i
prosjektet.
Problemet her er at du vil ikke forstyrre Sally, som er i full
gang med å fikse småfeil her og der.
Hun er avhengig av at den seneste versjonen av prosjektet (i
/calc/trunk) alltid fungerer.
Hvis du starter med å legge inn forandringene dine bit for bit,
vil du ganske sikkert ødelegge ting for Sally.
En strategi er å krabbe inn i et hull; du og Sally kan stoppe
med å dele informasjon for en uke eller to.
Det vil si, starte med å omorganisere alle
filene i arbeidskopien din, men ikke legge inn eller oppdatere før
du er helt ferdig med oppgaven.
Men det er en del problemer med denne metoden.
For det første er det ikke særlig trygt.
Folk flest liker å lagre arbeidet sitt til depotet med jevne
mellomrom i tilfelle noe stygt skulle skje med arbeidskopien.
For det andre er det ikke spesielt fleksibelt.
Hvis du gjør arbeidet ditt på forskjellige datamaskiner (kanskje
du har en arbeidskopi av /calc/trunk på to
forskjellige maskiner) må du kopiere forandringene manuelt fram og
tilbake, eller gjøre hele jobben på en enkelt maskin.
På samme måte er det vanskelig å dele forandringene dine som er
under utvikling med andre.
Vanlig god praksis innen programutvikling er å la dine kolleger få
se over arbeidet ditt mens du holder på.
Hvis ingen ser innleggingene dine, går du glipp av potensiell
respons.
Til slutt, når du er ferdig med alle forandringene dine, kan du
oppleve at det er veldig vanskelig å flette sammen det endelige
resultatet ditt med resten av koden til firmaet.
Sally (eller andre) kan ha gjort mange forandringer i depotet som
er vanskelig å legge inn i arbeidskopien din – spesielt hvis du
kjører svn update etter flere uker med
isolasjon.
En bedre løsning er å opprette din egen forgrening, eller utviklingslinje, i depotet. Dette lar deg lagre det halvfungerende resultatet ditt med jevne mellomrom uten å blande det med arbeidet til andre, og samtidig kan du velge ut informasjon som du vil dele med dine kolleger. Du vil etter hvert få se nøyaktig hvordan dette fungerer.
Det å opprette en ny gren er veldig enkelt – du lager en
kopi av prosjektet i depotet ved å bruke kommandoen svn
copy.
Subversion er ikke bare i stand til å kopiere enkle filer, men
også hele kataloger.
I dette tilfellet vil du lage en kopi av
/calc/trunk-katalogen.
Hvor skal den nye kopien være?
Hvor du vil – det er et spørsmål om prosjektrutiner.
La oss si at teamet ditt har som regel å opprette forgreninger i
/calc/branches-området i depotet, og du vil
kalle grenen din my-calc-branch.
Det du vil er å lage en ny katalog,
/calc/branches/my-calc-branch, som begynner
livet som en kopi av /calc/trunk.
Det er to forskjellige måter å lage en kopi på.
Vi vil demonstrere den rotete måten først, bare for å klargjøre
konseptet.
Til å begynne med, hent ut en arbeidskopi av prosjektets
rotkatalog, /calc:
$ svn checkout http://svn.example.com/repos/calc bigwc A bigwc/trunk/ A bigwc/trunk/Makefile A bigwc/trunk/integer.c A bigwc/trunk/button.c A bigwc/branches/ Sjekket ut revisjon 340.
For å lage en kopi er det nå bare å angi to arbeidskopistier til kommandoen svn copy:
$ cd bigwc $ svn copy trunk branches/my-calc-branch $ svn status A + branches/my-calc-branch
I dette tilfellet kopierer svn copy
katalogen trunk rekursivt til en ny
arbeidskatalog, branches/my-calc-branch.
Som du kan se av kommandoen svn status er den
nye katalogen nå klargjort for å legges til i depotet.
Men legg også merke til “+”-tegnet ved siden av
bokstaven A.
Dette indikerer at den klargjorte tilleggingen er en
kopi av noe, og ikke noe nytt.
Når du legger inn forandringene dine, vil Subversion lage
/calc/branches/my-calc-branch i depotet ved
å kopiere /calc/trunk istedenfor å sende
hele arbeidskopien over nettverket en gang til:
$ svn commit -m "Lager en privat gren av /calc/trunk." Legger til branches/my-calc-branch La inn revisjon 341.
Og nå den lettere måten å lage en gren på, som vi skulle fortalt deg om til å begynne med: svn copy kan operere direkte mot to URLer.
$ svn copy http://svn.example.com/repos/calc/trunk \
http://svn.example.com/repos/calc/branches/my-calc-branch \
-m "Lager en privat gren av /calc/trunk."
La inn revisjon 341.
Det er egentlig ingen forskjell på disse to metodene.
Begge prosedyrene lager en ny katalog i revisjon 341, og den nye
katalogen er en kopi av /calc/trunk.
Dette er vist i Figur 4.3, “Depot med ny kopi”.
Legg merke til at den andre metoden utfører en
øyeblikkelig innlegging.[19]
Det er en lettere prosedyre, fordi det ikke kreves at du må
hente ut et stort speil av depotet.
Faktisk trenger du med denne teknikken ikke en arbeidskopi i det
hele tatt.
Nå som du har laget en gren av prosjektet, kan du hente ut en ny arbeidskopi for å starte bruken av den:
$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch A my-calc-branch/Makefile A my-calc-branch/integer.c A my-calc-branch/button.c Sjekket ut revisjon 341.
Det er ingenting spesielt med denne arbeidskopien; den
avspeiler simpelthen bare en annen katalog i depotet.
Men når du legger inn forandringer, vil ikke Sally se noen av
dem når hun oppdaterer.
Hennes arbeidskopi er fra /calc/trunk.
(Pass på å lese “Bytte om en arbeidskopi”
senere i dette kapittelet:
Kommandoen svn switch er en alternativ måte å
lage en arbeidskopi av en forgrening.)
La oss late som om en uke går, og de følgende innlegginger blir gjort:
Du gjør en forandring i
/calc/branches/my-calc-branch/button.c
som lager revisjon 342.
Du gjør en forandring i
/calc/branches/my-calc-branch/integer.c
som lager revisjon 343.
Sally gjør en forandring i
/calc/trunk/integer.c som lager
revisjon 344.
Det er nå to uavhengige utviklingslinjer, vist i Figur 4.4, “Forgreningen av ei fils historie”, som skjer med
integer.c.
Ting blir interessante når du ser på historien til
forandringene gjort i din kopi av
integer.c:
$ pwd /home/user/my-calc-branch $ svn log --verbose integer.c ------------------------------------------------------------------------ r343 | bruker | 2002-11-07 15:27:56 -0600 (tor, 07 nov 2002) | 2 lines Endrede filstier: M /calc/branches/my-calc-branch/integer.c * integer.c: frozzled the wazjub. ------------------------------------------------------------------------ r341 | bruker | 2002-11-03 15:27:56 -0600 (tor, 07 nov 2002) | 2 lines Endrede filstier: A /calc/branches/my-calc-branch (fra /calc/trunk:340) Lager en privat gren av /calc/trunk. ------------------------------------------------------------------------ r303 | sally | 2002-10-29 21:14:35 -0600 (tir, 29 okt 2002) | 2 lines Endrede filstier: M /calc/trunk/integer.c * integer.c: Forandret en docstring. ------------------------------------------------------------------------ r98 | sally | 2002-02-22 15:35:29 -0600 (fre, 22 feb 2002) | 2 lines Endrede filstier: M /calc/trunk/integer.c * integer.c: Legger til denne fila i prosjektet. ------------------------------------------------------------------------
Legg merke til at Subversion går gjennom historien av
forgreningens integer.c hele veien tilbake
gjennom tiden og krysser til og med punktet den ble kopiert.
Opprettelsen av forgreningen vises som en hendelse i historien,
fordi integer.c også ble kopiert når alt
under /calc/trunk/ ble kopiert.
Se nå hva som skjer når Sally kjører den samme kommandoen på
hennes kopi av fila:
$ pwd /home/sally/calc $ svn log --verbose integer.c ------------------------------------------------------------------------ r344 | sally | 2002-11-07 15:27:56 -0600 (tor, 07 nov 2002) | 2 lines Endrede filstier: M /calc/trunk/integer.c * integer.c: Ordnet en dunge med skrivefeil. ------------------------------------------------------------------------ r303 | sally | 2002-10-29 21:14:35 -0600 (tir, 29 okt 2002) | 2 lines Endrede filstier: M /calc/trunk/integer.c * integer.c: Forandret en docstring. ------------------------------------------------------------------------ r98 | sally | 2002-02-22 15:35:29 -0600 (fre, 22 feb 2002) | 2 lines Endrede filstier: M /calc/trunk/integer.c * integer.c: Legger til denne fila i prosjektet. ------------------------------------------------------------------------
Sally ser at hennes egen revisjon 344 forandrer seg, men ikke forandringen som du gjorde i revisjon 343. Hva Subversion angår, påvirket disse to innleggingene forskjellige filer på forskjellige plasseringer i depotet. Subversion viser imidlertid at de to filene deler en felles historie. Før grenkopieringen ble gjort i revisjon 341 var de den samme fila. Det er derfor både du og Sally ser forandringene gjort i revisjonene 303 og 98.
Det er to viktige ting du bør huske fra denne seksjonen.
Ulikt mange andre versjonskontrollsystemer eksisterer Subversions forgreninger som vanlige filsystemkataloger i depotet, ikke i en ekstra dimensjon. Disse katalogene inneholder bare noe ekstra historisk informasjon.
Subversion har ikke noe internt begrep om en gren – bare kopier. Når du kopierer en katalog, er den resulterende nye katalogen bare en “gren” fordi du legger denne meningen til den. Du kan tenke på denne katalogen på en spesiell måte eller behandle den forskjellig, men for Subversion er den bare en vanlig katalog som tilfeldigvis er blitt opprettet ved kopiering.
[19] Subversion støtter ikke kopiering mellom forskjellige depot. Når du bruker URLer med svn copy eller svn move kan du bare kopiere elementer innenfor det samme depotet.