©2002-2011 Michael Knudsen.
$Date: 2011/05/26 19:54:29 $
Dette eller uddrag heraf må under ingen omstændigheder distribueres på nogen form. Dette vil måske ændre sig, når indhold, layout, struktur etc. er tilfredsstillende.
Ved semesterstart på Basis er det normalt relativt få, der kender til CVS, og disse har sjældent nogen egentlig erfaring med at bruge det. Derfor ved mange desværre ikke, at de kan bruge CVS til at håndtere deres filer til rapporter og lignende.
Denne guide er et forsøg på at introducere CVS på en måde, som gør det nemt at tage i brug i forbindelse med projekter på Basis.
Undlad at falde for fristelsen til at springe teksten over og blot udføre teksten i kommandoboksene, da du efter al sandsynlighed ikke får den grundlæggende forståelse for CVS' virkemåde og derfor risikerer at splitte noget ad eller anvende CVS forkert.
Til sidst skal du være klar over, at det endelige ansvar er dit. Der er dog gjort store anstrengelser for at holde denne guide så korrekt og præcis som muligt, så risikoen for problemer skulle være lille, hvis du vel at mærke læser og forstår den forklarende tekst.
CVS er et system/program til versionsstyring, der blandt andet tillader at flere personer kan arbejde samtidig på et fælles sæt dokumenter. Dette kan være utroligt nyttigt i forbindelse med rapportskrivning til projekter, men det kan også bruges til styring af mange andre ting:
Har man een gang prøvet at arbejde flere på et fælles sæt dokumenter, ved man, at det er en træls opgave at koordinere. Har man een gang arbejdet med et (godt) versionsstyringssystem, kan man slet ikke forstå, at andet kan lade sig gøre med et acceptabelt resultat.
CVS kan hentes fra det officielle CVS-website.
Projektet styret med CVS skal skelnes imellem den egentlige produktionsudgave, REPOSITORY, og en eller flere arbejdskopier, CHECKOUT. CVS' repository er reelt blot et bibliotek (en mappe) på en computer, der indeholder en række MODULER. Et modul er reelt blot et bibliotek under repository, der typisk indeholder filer, som udgør eksempelvis eet projekt, eet program eller lignende selvstændige enheder.
CVS' funktion består meget kort fortalt i at forene produktionsudgaven med ændringerne fra en brugers arbejdskopi og holde styr på disse ændringer. Ændringer påvirker udelukkende brugerens egen arbejdskopi, så man skal fortælle CVS, når man ønsker at gøre ens ændringer tilgængelige for alle andre. Dette kaldes et COMMIT. Det betyder, at man kan arbejde på sin egen kopi af projektet uden at forstyrre eller ødelægge noget for de andre i gruppen, og dette er en meget stor fordel. Det kræver dog den disciplin, at man ikke committer noget, der ikke fungerer, som det skal. Hvis man eksempelvis har lavet nogle ændringer i et program til projektet, skal man sikre sig, at det kan compiles, inden man committer. Denne opgave kan automatiseres af CVS, men det bør dog klares med en politisk (ikke-teknisk) løsning hvis muligt, så respektér hinanden ved at checke alle ændringer for fejl og eventuelle småproblemer.
Der er mange styrker ved CVS. Eksempelvis kan man hente tidligere udgaver af dokumenter frem. Dette kan være meget nyttigt, hvis nogen splitter noget i rapporten ad. Man henter blot en tidligere, fungerende version frem, som man bytter ud med den eksisterende. Man kan også følge med i de ændringer, der laves, og finde den ansvarlige for de enkelte ændringer. Alle ændringer (på fil-basis) tilknyttes en kommentar (en log-besked), som også gør det nemt at følge ændringer, hvis man vel at mærke skriver, hvad man har ændret. Beskeder ala "Ændringer." er komplet ubrugelige.
CVS kan sættes op til at sende email, når der committes. Dette kan være en god idé at bruge, da hele gruppen automatisk bliver informeret om alle ændringer. Ikke alle er interesserede i at modtage disse beskeder, og kun få læser dem i praksis, så afgør på et gruppemøde, om dette skal gøres.
I det følgende gennemgås de basale og nødvendige kommandoer for at anvende CVS. Der er eksempler til alle kommandoer, men spring ikke blot fra eksempel til eksempel, da forklaringen er det vigtige. Slavisk gennemgang af eksempler kan potentielt skade din gruppes arbejde, hvis nogen allerede har sat CVS op.
Bemærk: Dette skal kun gøres een gang, og kun et enkelt medlem skal gøre dette.
Når man begynder på en ny projektperiode, får hver gruppe et projektbibliotek, og det er fornuftigt at lægge repository her. Følgende notation og antagelser gælder i resten af dokumentet:
$ kommando1 parameter1 parameter2 parameter3 output og atter output $ kommando2 parameter nyt output
Find ud af, hvilken gruppe du er i med kommandoen (du skal naturligvis bruge den, der er forskellig fra dit brugernavn):
$ groups tt121847 34grb339
Først skal repository oprettes. Man bruger kommandoen cvs init, og den opretter repository ud fra CVSROOT-variablen. Gør derfor således:
$ export CVSROOT=/projekt/34grb339/cvsroot $ cvs init
Alternativt kan man benytte en anden notation, der er fuldstændig ækvivalent:
$ cvs -d /projekt/34grb339/cvsroot
Bruger man csh eller tcsh (dette er standardshell på CS/datalogistudiet), er den tilsvarende syntaks til første eksempel:
$ setenv CVSROOT /projekt/34grb339/cvsroot $ cvs init
Nu har du et fungerende repository, hvis der ikke er sket fejl. Det er nu på tide at oprette nogle moduler. Dette gøres ved at opbygge et midlertidigt repository et sted. Benyt /tmp til dette, da det netop er beregnet til midlertidige filer:
$ cd /tmp $ mkdir repository $ cd repository $ mkdir rapport eksamen www source
Her er oprettet moduler til rapporten, eksamenspapirer (eksempelvis et slideshow eller notater), gruppens hjemmeside og kildekode til eventuel implementation. De skal nu importeres i det rigtige repository:
$ cvs import -m "Importeret biblioteksstruktur." . B339 start cvs import: Importing /projekt/34grb339/cvsroot/./rapport cvs import: Importing /projekt/34grb339/cvsroot/./www cvs import: Importing /projekt/34grb339/cvsroot/./eksamen cvs import: Importing /projekt/34grb339/cvsroot/./source No conflicts created by this import $ cd .. $ rm -fr repository
En forklaring af vigtige ting:
Herefter kan man se, at der ikke opstod fejl i forbindelse med importeringen. De sidste to kommandoer fjerner blot det midlertidige repository. Havde man udeladt log-beskeden, ville CVS have startet en editor, der på dolomit.but.auc.dk normalt er emacs i tekstmode. Dette kan ændres ved at sætte CVSEDITOR-variablen, eksempelvis:
$ export CVSEDITOR="vi"
Det nemmeste og hurtigste er dog at skrive log-beskeden på kommandolinien.
Dette er faktisk alt, man skal gøre for at oprette et repository, og man kan nu gå i gang med at arbejde på det. Dette kræver, at man henter en arbejdskopi, dvs. udfører et checkout.
Når man har oprettet et repository og vil arbejde på det, skal man først lave et checkout. Dette gøres ganske enkelt således:
$ cd $ export CVSROOT=/projekt/34grb339/cvsroot $ cvs checkout rapport cvs checkout: Updating rapport
Bemærk: Dette skal kun gøres een gang per bruger. Man bruger cvs update, når man skal opdatere sin arbejdskopi. Mere om dette senere.
Man har nu et bibliotek, rapport, liggende. Biblioteket indeholder eet bibliotek, CVS, der indeholder nogle kontrolfiler til CVS. En af disse, CVS/Root, indeholder stien til det anvendte repository, og man behøver derfor ikke sætte CVSROOT-variablen, næste gang man skal arbejde på sin arbejdskopi. Man skal undlade at lave om på noget i CVS-biblioteket, hvis man ikke har forstand på CVS. Hvis man har det, læser man nok ikke dette.
Man har nu en arbejdskopi liggende, som man kan arbejde på. Da den er tom, vil man sandsynligvis tilføje nogle filer til den.
Det følgende afsnit vil præsentere kommandoer, som ofte bruges i det almindelige, daglige arbejde med CVS. De er derfor vigtige at kende.
Når man vil tilføje filer til sin arbejdskopi, opretter man reelt blot filerne i biblioteket, der indeholder arbejdskopien. Det betyder dog ikke, at de automatisk underlægges CVS-kontrol -- det ville ikke være hensigtsmæssigt i de fleste situationer. Man skal først fortælle CVS, at man har tilføjet filer til repository. Det gør man således:
$ cvs add main.tex cvs add: scheduling file `main.tex' for addition cvs add: use 'cvs commit' to add this file permanently
Som man kan se, er filen ikke tilføjet til repository endnu. Man skal huske, at man arbejder på sin arbejdskopi, og det er dén, man laver sine ændringer på. Disse ændringer er kun lokale, indtil man committer dem til repository. Bemærk i øvrigt, at man kan specificere flere filer ad gangen.
På et tidspunkt har man sikkert nogle filer, som man ikke længere skal bruge. Det er en god ide at fjerne dem fra repository, og det gør man således:
$ rm main.tex $ cvs remove main.tex cvs remove: removed `main.tex'
Man skal huske at slette (rm) filen, inden man fjerner den. Hvis man ikke gør dette, skal man benytte -f til remove:
$ cvs remove -f main.tex
Igen, filen bliver ikke fjernet fra repository, før man committer sine ændringer. Principielt bliver filen aldrig fjernet fra repository. Den får blot en ny version, som siger, at filen ikke eksisterer. Det betyder, at man godt kan hente "slettede" filer frem igen.
Hvis man er flere, der arbejder på samme projekt, er det en god idé ofte at opdatere sin arbejdskopi, så man får andres (comittede) ændringer tilføjet. Man synkroniserer ét modul ad gangen, og man skal være i modulets bibliotek. Det gøres let med denne kommando:
$ cd rapport $ cvs update -Pd cvs update: Updating . P main.tex U konklusion.tex M litteratur.bib ? Makefile.bak retrieving revision 1.41 retrieving revision 1.43 Merging differences between 1.41 and 1.43 into Makefile rcsmerge: warning: conflicts during merge cvs server: conflicts found in Makefile C Makefile
Når man har lavet ændringer i sin arbejdskopi, skal de filføjes til repository. Det er en god idé at gøre dette ofte, da man kan undgå mange konflikter. Man skal dog ikke committe, før man er helt færdig med sine ændringer. Dvs. hvis man skal rette tre sider igennem, skal man først committe, når man har rettet alle tre sider. Ydermere bør man som sagt sikre sig, at projektet er konsistent, dvs. at det compiler uden problemer. Inden man committer, undersøger CVS, om man har synkroniseret med repository. Hvis man ikke har det, afviser det at tilføje ens ændringer.
Således committer man sine ændringer:
$ cvs commit -m "Smårettelser: kommafejl etc." cvs commit: Examining . Checking in main.tex; /projekt/34grb339/cvsroot/rapport/main.tex,v <-- main.tex new revision: 1.3; previous revision: 1.2 done
Det er vigtigt at kunne løse konflikter, da man i løbet af et projekt højst sandsynligt vil støde på dem -- især i forbindelse med rettearbejde, hvor alle typisk retter i hele rapporten. Når der opstår en konflikt, indsætter CVS de andre ændringer i arbejdskopien, men det beholder ens egne ændringer.
I filen med konflikten vil konfliktens begyndelse markeres med otte "mindre end"-tegn, dvs. '<<<<<<<<', og herefter vil ens egne ændringer følge. Slutningen på ens egne ændringer markeres med otte lighedstegn, dvs. '========', og herefter følger de konfliktérende ændringer. Slutningen på disse markeres med otte "større end"-tegn efterfulgt af revisionsnummeret, dvs. '>>>>>>>> x.y'.
En konflikt kunne se således ud:
int
main(int argc, char **argv)
{
<<<<<<<<
unsigned int major=0, minor=99;
printf("Lollypop v%i.%i by Dick Taid\n", major, minor, author);
========
char *version = "Lorliporp v0.97 by Duck Toad\n";
puts(version)
>>>>>>>> 1.2
return(0);
}
Nu skal man så finde en god løsning på problemet. Der kan være flere konflikter i samme dokument, og man skal huske at løse dem alle. Hvis man arbejder med flere dokumenter, kan der være konflikter i flere filer. Til sidst skal man committe sine ændringer, hvis de er klar til at blive tilføjet til repository. Hvis nogen gang på gang committer noget bras, der splitter det hele ad, kan det være nødvendigt for gruppen at aftale, at man uden videre må erstatte andres ændringer med tidligere versioner.
Flertallet af alle konflikter skyldes mangel på ordentlig kommunikation i gruppen, så det er vigtigt at have aftalt præcise opgaver. CVS er ikke en afløser for velfungerende kommunikation, og mangel på dette vil normalt straffes hårdt til eksamen. Aftal også med det samme, om man er ansvarlig for et afsnit, og i hvilket omfang man må rette i andres arbejde. Ansvarlighed for afsnit dækker over retten til at fjerne andres ændringer fra det uden at konsultere gruppen først.
Som nævnt holder CVS en log over ændringerne. Dette er meget nyttigt, hvis man skal se, hvad andre har lavet.
Således findes loggen frem:
$ CVS log main.tex RCS file: /projekt/34grb339/cvsroot/rapport/main.tex,v Working file: main.tex head: 1.91 branch: locks: strict access list: symbolic names: keyword substitution: kv total revisions: 91; selected revisions: 91 description: ---------------------------- revision 1.91 date: 2002/05/26 23:04:14; author: mk267673; state: Exp; lines: +1-1 Rettet en kommafejl i main.tex. ---------------------------- revision 1.90 date: 2002/05/26 22:53:58; author: mk267673; state: Exp; lines: +2-1 Rettet en apostrof-s-fejl og tilføjet en typeout, der minder os om at opdatere sidetallet. [...]
Output vil typisk være langt, så det kan normalt godt betale sig at pipe det ud i en pager som eksempelvis less:
$ cvs log main.tex | less
"|" kaldes "pipe" og betyder, at output fra processen til venstre gives som input til processen til højre. Med less som pager kan man scrolle op og ned i teksten, og det er meget rart, når man skal læse CVS-logs. Tryk "q" for at forlade less og komme tilbage til kommandoprompten.
De fleste af CVS' kommandoer kan forkortes, så man slipper for at skrive så meget. Eksempelvis kan checkout erstattes med co, commit med ci og update med up. Det er spild af plads og tid at bringe en hel liste her, så eksperimentér selv.
Ofte arbejder man på projektet hjemmefra, men hvis man ikke har en fast eller hurtig internetforbindelse, er det ikke så smart. Imidlertid tillader CVS også, at man arbejder på et projekt, der har sit repository på en anden computer, så også her er CVS nyttigt at bruge. I det følgende er en kort forklaring på, hvordan man kommer i gang med dette. Igen er der nogle antagelser, der skal gøres klart:
Først skal CVS oplyses om, at der skal bruges ssh til at forbinde sig til repository, da dolomit ikke tillader rsh-forbindelser udefra. Det gøres ved at sætte shell-variablen CVS_RSH:
$ export CVS_RSH="ssh"
Det anbefales, at man indsætter kommandoen (eller en tilsvarende hvis man bruger en anden shell) i sin .bashrc. Hvis man ikke kender til ssh, bør man læse denne udmærkede introduktion til ssh.
Nu skal man lave et checkout af repository, og det gør man på næsten samme måde, som når det ligger lokalt. CVSROOT skal blot sættes til noget andet, og det er en god idé at signalere, at man ønsker at benytte kompression, da opdateringer overføres hurtigere:
$ cd $ export CVSROOT=tt121447@dolomit.but.auc.dk:/projekt/34grb339/cvsroot $ cvs -z9 checkout rapport tt121447@dolomit.but.auc.dk's password: cvs server: Updating rapport
Igen skal man bemærke, at CVS holder styr på stien til dit repository, og du behøver derfor ikke sætte CVSROOT næste gang, du skal arbejde på din arbejdskopi. "-z9" indikerer, at man ønsker at bruge maksimal kompression. Tallet 9 kan erstattes med et hvilket som helst i intervallet fra 0 til og med 9. Man kan benytte kompression med alle CVS-kommandoer, og det kan godt betale sig. Hvis man gør dette, bør man slå kompression i ssh fra, da det kan give dårligere overførselshastighed.
I det følgende vil være nogle eksempler på avanceret brug af CVS. Disse er ikke nødvendige for at bruge CVS, men de er meget nyttige at kunne i mange situationer.
Det sker alt for tit, at nogen committer noget bras, der splitter det hele ad. Dette er ganske enkelt respektløst overfor resten af gruppen, og det bedste at gøre er at hente den tidligere version frem. Så kan vedkommende, der har splittet tingene ad, have besværet med at få tingene på plads.
Det er relativt enkelt at gøre. Man finder først ud af, hvilke filer der er ændret. Det er en god idé at holde øje med, hvilke filer der opdateres under update, da det kan lette dette arbejde væsentligt. Ved brug af loggen kan man nu finde revisionsnummeret på den korrekte udgave af filen samt det seneste revisionsnummer. Man laver nu et update, hvor man joiner de to revisioner. I det følgende eksempel antages det, at den korrekte version er 1.8 og den nuværende version er 1.10:
$ cvs update -j 1.10 -j 1.8 main.tex RCS file: /projekt/34grb339/cvsroot/rapport/main.tex,v retrieving revision 1.10 retrieving revision 1.8 Merging differences between 1.10 and 1.8 into main.tex
Revision 1.8 af main.tex er nu fundet frem og kan committes. Bemærk rækkefølgen: Først den nuværende og derefter den korrekte.
Nogle gange kommer man til at skrive noget i loggen, som man fortryder af forskellige grunde. Dette kan godt rettes, men bemærk, at hvis man udsender email med commitbeskeder, er den oprindelige besked udsendt. Den nye besked udsendes ikke på email, og eventuelle uheldige ytringer om andre gruppemedlemmers evner, udseender eller mødre kan ikke kaldes tilbage:
$ cvs admin -m 1.11:"Nu compiler det igen." main.tex RCS file: /projekt/34grb339/cvsroot/rapport/main.tex,v done
Husk at skrive filnavnet. Hvis det er den samme besked i flere filer, skal de ændres een ad gangen. Bemærk, at der ikke må være mellemrum mellem versionsnummeret, kolonet og den nye commitbesked.
Opsætning af commitmail kan være meget fornuftigt til projektarbejde, da man gøres opmærksom på alle ændringer.
Man skal ændre i en af kontrolfilerne til CVS, CVSROOT/loginfo, for at sætte dette op:
$ cd /tmp $ export CVSROOT=tt121447@dolomit.but.auc.dk:/projekt/34grb339/cvsroot $ cvs checkout CVSROOT/loginfo U CVSROOT/loginfo $ emacs CVSROOT/loginfo $ cvs commit CVSROOT/loginfo Checking in CVSROOT/loginfo; /projekt/34grb339/cvsroot/CVSROOT/loginfo,v <-- loginfo new revision: 1.8; previous revision: 1.7 done cvs commit: Rebuilding administrative file database
Det er dog ikke helt enkelt, hvordan CVSROOT/loginfo skal se ud. Der står normalt en masse i filen i forvejen, men dette kan man blot slette, hvis man vil. Her er et eksempel på en korrekt CVSROOT/loginfo:
rapport cat | grep -v "In directory" | mailx -s "B339 CVS: rapport" b339@but.auc.dk source cat | grep -v "In directory" | mailx -s "B339 CVS: source" b339@but.auc.dk
Denne opsætning sørger for, at alle modtager commitmail, når der sker ændringer til modulerne med rapporten eller implementationen. Hvis man ønsker commitmail på alle moduler, skriver man blot:
DEFAULT cat | grep -v "In directory" | mailx -s "B339 CVS: commitmail" b339@but.auc.dk
Her vil det dog ikke fremgå af emnet, hvilket modul der er ændret. Man kan naturligvis lave nogle scripts, så ændringerne også sendes med, men det vil denne guide ikke behandle, da formatet af dette eksempel er godt nok til de fleste. Samtidig er det kun et fåtal, der kan (og vil) læse outputtet, og det er jo netop meningen, at ændringerne skal fremgå af beskeden. Det er desuden forfatterens oplevelse, at bruges der commitmail med ændringer, skrives der ubrugelige beskeder, og ingen læser alligevel ændringerne.
Hvis man alligevel vil have ændringerne med, kan man bruge følgende:
Forfatteren er dog helt uforstående over for anvendelsen af dette og har ingen erfaring med opsætning eller lignende.
Nogle gange kan det være nyttigt at se, hvornår en given linie sidst er blevet ændret. Dette gør man med CVS-kommandoen annotate:
$ cvs annotate main.c
Annotations for main.c
***************
1.1 (tt121447 03-Oct-02): int
1.1 (tt121447 03-Oct-02): main(int argc, char **argv)
1.1 (tt121447 03-Oct-02): {
1.2 (tc462478 04-Oct-02): unsigned int major=0, minor=99;
1.1 (tt121447 03-Oct-02):
1.3 (tc462478 04-Oct-02): printf("Lollypop v%i.%i by Dick Taid\n", major, minor);
1.1 (tt121447 03-Sep-02): exit(EXIT_SUCCESS);
1.5 (tc462478 03-Sep-02): }
Kommandoen er meget nyttig til at finde ud af, hvornår en fejl blev introduceret i noget kode, når man har identificeret den. Dette gør det meget let at finde ud af, hvem der skal hoste op med chokolade etc. til resten af gruppen. I projektarbejde kan dette vise sig at være et uundværligt redskab, der kan afgøre skyldsspørgsmål langt hurtigere end et gruppemøde.
Denne guide forklarer langtfra udtømmende om CVS, så derfor gives i det følgende nogle henvisninger til andre ressourcer.
Denne guide er udelukkende ment som en introduktion, og derfor er der mange aspekter i brugen af CVS, der ikke bliver behandlet. Med dette afsnit forsøges at råde bod på dette ved at henvise til ressourcer, der supplerer det manglende.
I mange tilfælde kan det være rart at have læseadgang til data i CVS via en webbrowser. Der findes flere løsninger til dette, men fælles for dem alle er, at forfatteren ikke har nogen erfaring med opsætningen af dem.
Mange bruger Windows™, og der findes også windowsklienter til CVS. Bemærk dog, at mange windowsprogrammer gemmer data i et binært format, som gør det upraktisk at benytte CVS til disse data, fordi CVS ikke kan flette ændringer i binære filer sammen.