Laboratorium 3 - CVS


Czym jest CVS

  1. CVS (Concurrent Versions System) - narzędzie do zarządzania kodem źródłowym. CVS wspomaga pracę z kodem źródłowym (ogólnie: dowolnego rodzaju plikami) gdy nad kodem tym pracuje wielu ludzi jednocześnie.

  2. Pojęcia repozytorium (repository) i katalogu roboczego (working directory)
    • zmienna środowiskowa CVSROOT

  3. Polecenie cvs - sposób użycia
    cvs [opcje_ogolne] komenda [opcje_komendy] [argumenty_komendy]
    
  4. Przykładowe repozytorium dostępne przez www

  5. Strona domowa CVS

  6. Następca: Subversion

Podstawowe komendy polecenia cvs

  1. init - tworzenie repozytorium
    cvs -d "$HOME/cvsroot" init
    
    albo
    export CVSROOT="$HOME/cvsroot"
    cvs init
    
  2. import - wprowadzanie istniejacego zbioru plikow do repozytorium
    cvs import bigint balis start
    
    Uwaga! Komenda import wprowadza do repozytorium CVS zawartosc katalogu biezacego wraz z podkatalogami! Oznacza to, ze gdy chcemy wprowadzic jakis projekt do repozytorium, trzeba najpierw wejsc do glownego katalogu tego projektu. Pierwszy parametr komendy import (w tym przykladzie 'bigint') oznacza nazwe modulu w CVS, w ktorym zapisane zostana zaimportowane pliki (nie jest to nazwa katalogu, ktory nalezy zaimportowac!). Dwa pozostale argumenty to znaczniki - jako pierwszy mozna wpisac np. swoj login, jako drugi slowo 'start'.

  3. checkout (lub: 'co', 'get') - pobranie plikow z repozytorium
    cvs checkout bigint
    
  4. commit - wpisanie zmian dokonanych w katalogu roboczym do repozytorium
    cvs commit
    
  5. add - dodanie nowego pliku do projektu
    cvs add bigint.h
    
  6. update - uaktualnienie plików w katalogu roboczym
    cvs update 
    cvs update bigint.h
    cvs update -r 1.2 bigint.h
    cvs update -A -P -d
    
  7. release - zakończenie sesji, usunięcie katalogu roboczego
    cvs release
    

Zdalny dostęp do repozytorium CVS

  1. Metoda pserver
    • ustawienie zmiennej CVSROOT (bash)
      export CVSROOT=:pserver:user@hostname:/sciezka/do/repozytorium
      
    • rozpoczęcie pracy - cvs login - logowanie się do repozytorium
    • potem - normalna praca przy użyciu dowolnych komend CVS

  2. Przez ssh
    • ustawienie zmiennych środowiskowych (bash)
      export CVSROOT=user@hostname:/sciezka/do/repozytorium
      export CVS_RSH=ssh
      export CVS_SERVER=/usr/bin/cvs
      
    • potem - normalna praca przy użyciu dowolnych komend CVS

  3. Dygresja: dostep przez ssh przy uzyciu kluczy (bez podawania hasla)
    • Generujemy pare kluczy - prywatny i publiczny:
      ssh-keygen -t rsa
      W katalogu $HOME/.ssh powstaja pliki id_rsa - klucz prywatny, oraz id_rsa.pub - klucz publiczny. Uwaga! Nalezy chronic klucz prywatny przed dostaniem sie w niepowolane rece! Przy generowaniu klucza mozna dodatkowo ochronic klucz prywaty haslem - wtedy przy logowaniu bedziemy rowniez pytani o to haslo.

    • Jesli chcemy, zeby z hosta A logowac sie na host B przy uzyciu klucza, to nalezy klucz publiczny z hosta A wpisac do pliku .ssh/authorized_keys na hoscie B.

    • W naszym wypadku powinno wystarczyc:
      cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
      Powinno to umozliwic bezhaslowe logowanie sie z maszyn lokalnych na serwer fatcat przy pomocy polecenia ssh fatcat (dzieku temu, ze katalog domowy na obu maszynach jest dzielony przez sieciowy system plikow).

Konflikty

Czasem podczas próby zapisu zmian do repozytorium (cvs commit) wystąpi konflikt jesli ktoś w miedzyczasie zmodyfikowal ten sam plik. Wtedy zapisanie zmian nie jest mozliwe. Nalezy najpierw uaktualnic plik (cvs update). Konflikty zostana albo automatycznie rozwiazane, albo zaznaczone w pliku, tak aby uzytkownik usunal je recznie. Sekcja, w ktorej wystepuje konflikt jest w pliku zaznaczona w nastepujacy sposob:
<<<<<<<
wersja lokalna
=======
wersja zdalna
>>>>>>>

Ćwiczenie

Celem ćwiczenia jest współbieżna edycja jednego pliku przez wiele osób
  1. Serwer: fatcat.ftj.agh.edu.pl
  2. Ścieżka do repozytorium: /tmp/cvsroot2
  3. Nazwa modulu: imiona
  4. Należy pobrać z repozytorium katalog imiona (konieczny zdalny dostep!).
  5. W katalogu tym jest plik o nazwie `imiona.txt', do którego należy wpisać swoje imię i nazwisko, a następnie zapisać zmiany do repozytorium.
  6. Proszę próbować modyfikować plik i zapisywać go do repozytorium aż do otrzymania konfliktów.

Wersje plików

  1. cvs log - historia zmian.

    Komenda cvs log wyświetla historię pliku, tj. informacje o kolejnych wersjach wraz z komentarzami. Przykład:

    cvs log bigint.cpp
    

  2. cvs status - status plików

    Komedna cvs status wypisuja aktualny status pliku, tj. jego ostatnią wersję, wersję w katalogu roboczym, etc.

    cvs status bigint.cpp
    

  3. Użycie opcji -r

    • Opcja '-r' służy do podania numeru wersji, np. w połączeniu z komendą checkout służy do pobrania z repozytorium określonej wersji pliku (lub całego modułu):
      cvs checkout -r tag argumenty
      
      gdzie tag jest numerem wersji. Przykłady użycia:
      cvs checkout -r 1.1 bigint/bigint.cpp
      cvs checkout -r 1.1 bigint
      
    • Opcji '-r' można też używać z innymi poleceniami, np. update. Przykład:
      cvs update -r 1.3 bigint.cpp
      
      W tym przypadku komenda ta spowoduje uaktualnie wersji pliku bigint.cpp znajdującego się w bieżącym katalogu do wersji 1.3 (z ewentualnym uwzględnieniem konfliktow, etc.).

Rozgałęzienia (branches)

  1. Znaczniki (tags)

    Plik (lub cały moduł) można oznaczyć specjalnym symbolicznym znacznikiem. Potem można używać tego znacznika jako oznaczenia wersji. Do oznaczania plików służą dwie komendy: cvs tag i cvs rtag.

    • cvs tag nadaje plikom wsypecyfikowany znacznik. Używa plików z katalogu bieżącego, ale modyfikuje tylko repozytorium, tzn. nadaje znacznik plikom w tych wersjach, które znajdują się w katalogu bieżącym, jednak pliki w katalogu bieżącym nie będą posiadały tego znacznika. Przykład:
      cvs tag MOJ_TAG
      
    • cvs rtag różni się tym, że nie wymaga katalogu bieżącego, nadaje wyspecyfikowany znacznik określonym plikom znajdującym się w repozytorium. Może być połączony z opcją '-r'. Przykłady:
      cvs rtag MOJ_TAG bigint 
      
      - spowoduje przyznanie modułowi bigint w jego ostatniej wersji znacznika 'MOJ_TAG'.
      cvs rtag -r 1.1 MOJ_TAG bigint/bigint.cpp 
      
      - spowoduje przyznanie plikowi bigint/bigint.cpp w wersji 1.1 znacznika 'MOJ_TAG'.

    • Znaczników można używać zamiast numerów wersji, np.:
      cvs checkout -r MOJ_TAG bigint
      
  2. Rozgałęzienia

    • Załóżmy, że mamy stabilną wersję kodów źródłowych. Chcemy wprowadzać dalsze (eksperymentalne) modyfikacje, ale nie modyfikować głównego repozytorium, żeby nie stracić stabilności. Możemy utworzyć gałąź w repozytorium, w której będziemy rozwijać eksperymentalną wersję projektu, podczas gdy w głównym jego "pniu" pozostanie stara, stabilna wersja.

    • Przykład: po wypuszczeniu wersji 1.2 projektu decydujemy się utworzyć gałąź z eksperymentalnymi zmianami R1fix. Zarówno główny pień, jak i ta gałąź są rozwijane równolegle. Co pewien czas wprowadzamy kod z eksperymentalnej gałęzi do głównego pnia i kontynuujemy rozwój eksperymentalnego kodu.
      +-----+    +-----+    +-----+    +-----+    +-----+
      ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !   <- Główny pień
      +-----+    +-----+    +-----+    +-----+    +-----+
                      !                           *
                      !                          * (merge)
                      !                         *
                      !   +---------+    +---------+    +---------+
      Gałąź R1fix  -> +---! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !
                          +---------+    +---------+    +---------+
      
      
    • Gałąź tworzymy przy użyciu komendy rtag i opcji '-b', np.:
      cvs rtag -b MOJ_TAG bigint
      
      Komenda ta różni się tym od rtag bez opcji '-b', że samo rtag nadaje tylko symboliczne oznaczenie, zaś z opcją '-b' tworzy fizyczne rozgałęzienie w repozytorium, na którym można normalnie pracować.

  3. Scalanie zmian

    • W katalogu roboczym mamy pliki z glownego pnia repozytorium. Zeby scalic je ze zmianami dokonanymi w galezi branch_name, najlepiej zrobic to przy pomocy nastepujacej sekwencji komend:
      (1) cvs tag before_merge
      (2) cvs update -j branch_name test.java
      (3) cvs rtag -r branch_name branch_name_merged_on_date
      (4) cvs commit -m "komentarz" 
      (5) cvs tag after_merge
      

      (1) - Nadanie znacznika plikom w lokalnym katalogu roboczym przed scaleniem.

      (2) - Wprowadzenie zmian z galezi branch_name do katalogu roboczego.

      (3) - Nadanie znacznika branch_name_merged_on_date plikom w galezi branch_name w ich ostatniej wersji (zeby zaznaczyc, ze w tym miejscu galezi bylo ostatnie scalanie zmian).

      (4) - Wpisanie zmian do repozytorium - od tego momentu zmiany z galezi sa scalone z glownym pniem repozytorium.

      (5) - Nadanie znacznika plikom w lokalnym katalogu roboczym po scaleniu.

      Najwazniejsze jest polecenie (2). Nadawanie znacznikow w (1), (3) i (5) ulatwia pozniejsze zarzadzanie kodem i galeziami.

    • Zeby wprowadzic zmiany po raz kolejny, nalezy scalic zmiany dokonane tylko od czasu poprzedniego scalenia - zmienia sie polecenie (2):
      (1) cvs tag before_merge_on_date
      (2) cvs update -j branch_name_merged_on_date -j branch_name
      (3) cvs rtag -r branch_name branch_name_merged_on_date
      (4) cvs commit -m "komentarz" 
      (5) cvs tag after_merge_on_date
      

      (2) - Wprowadza zmiany dokonane pomiedzy wersja branch_name_merged_on_date a wersja branch_name (tj. wersja aktualna) z galezi do plikow w katalogu roboczym.

Zadania

  1. Proszę utworzyć nowe repozytorium CVS w swoim katalogu domowym (np. $HOME/cvsroot) i wpisać do niego pliki używane na zajęciach z Makefile lub Ant.
  2. Proszę pobrać z repozytorium do katalogu roboczego wpisane w zadaniu 1 pliki, wprowadzić w nich jakieś modyfikacje, wpisać zmiany do repozytorium, następnie obejrzeć historię zmian.
  3. Proszę utworzyć nową gałąź dla projektu w repozytorium. Do nowego katalogu proszę pobrać projekt z tej gałęzi. Proszę wprowadzić zmiany, następnie wpisać je do repozytorium. Proszę spróbować uaktualnić zmiany w poprzednim katalogu roboczym, który zawiera pliki z głownego pnia (a nie rozgałęzienia) i zobaczyć, jaki będzie efekt.
  4. Prosze scalic zmiany - wprowadzic zmiany z galezi do glownego pnia repozytorium.


Bartosz Baliś, balis at agh.edu.pl
Maciej Malawski, malawski at agh.edu.pl