Wrzasq.pl

SVN w praktyce

Thursday, 23 April 2009, 02:04

System kontroli wersji

Na początku zawsze jest chaos. Brak jakiegokolwiek planu działania, porządku, schematów - tylko wolność i swoboda. Tak zaczyna chyba każdy, kto w domowym zaciszu próbuje stawiać pierwsze kroki w programowaniu. Nie ma potrzeby, żeby programy dzielić na kilka plików, kod mający kilkadziesiąt, góra kilkaset linijek to już tasiemiec - kompiluje się go w ułamku sekundy i sprawdza czy działa; jeśli nie to patrzy dlaczego, jeśli tak to sprawdza, dlaczego tak, a nie inaczej. Zazwyczaj całe środowisko pracy to sam notatnik (wiem, że nie każdy używa Windows, ja pierwsze programy pisałem pod Linuksem i Amiga Workbench, ale przejmijmy, że to synonim "prostego edytora tekstu"). Z czasem jednak wszystko się rozwija - zaczyna się tworzyć coraz bardziej złożone rzeczy, notatnik zastępuje się IDE, odkrywa się, że zamiast wypisywać w każdej linijce śledzoną zmienną, można posłużyć się debuggerem. Ale wraz ze wzrostem złożoności tworzonych projektów trudniejsze jest nie tylko ich rozwijanie, ale również utrzymywanie - zaczyna się zauważać, jak wiele czynności staje się żmudnych i czasochłonnych. Zaczyna się pracować z innymi ludźmi i zachodzi potrzeba kontroli nad kodem (oraz innymi elementami projektów). Jednym z najbardziej pomocnych narzędzi zarówno przy samodzielnym grzebaniu w jakimś bardziej złożonym oprogramowaniu, jak i w pracy w zespole jest system kontroli wersji.

System kontroli wersji to narzędzie służące do zarządzania zamianami zachodzącymi w plikach. Udostępnia narzędzia/opcje wspomagające takie operacje jak scalanie, nanoszenie łat, śledzenie zmian, cofanie zmian, oraz wiele wiele innych. Prędzej, czy później każdy z systemem wersji się zetknie (w takiej, czy innej postaci). Przy większych przedsięwzięciach jest on praktycznie niezbędny. Kiedy może się nam on przydać? Powiedzmy, że tworzymy złożony system, musimy rozwiązać jakąś fundamentalną sprawę, jak na przykład kontrola dostępu. Jeśli za miesiąc się okaże, że zapędziliśmy się w ślepy zaułek i zamiast na przykład zwykłego poziomu dostępu potrzeba użyć masek bitowych, to nie musimy zaczynać od początku. Cofamy się do momentu, sprzed takiego wyboru (a może nawet część pracy wykonanej potem da się zachować i użyć w podobny sposób). Inny przykład - pracujesz z inną osobą w tym samym pliku nad innymi rzeczami: ty nad odczytem danych z pliku, on(a) nad wypisywaniem (przyjmijmy, że te rzeczy dzieją się w tym samym pliku :P) - możecie spokojnie pracować i po prostu przesłać swoje zmiany, a system naniesie je obie. Praca z samym kodem praktycznie się nie zmienia, nie potrzebne są żadne specjalne czynności - pracuje się na zwykłych plikach. W wielkim uproszczeniu możesz na razie wyobrazić sobie system kontroli wersji jako wyspecjalizowany serwer FTP.

Opiszę tutaj obsługę systemu SVN, ale to nie jedyne tego typu rozwiązanie - jest on po prostu najbardziej popularny (ze względu na łatwość obsługi i relatywnie małą złożoność). Oprócz SVN warto zainteresować się chociażby oprogramowaniem git - systemem kontroli wersji w architekturze P2P. Są też komercyjne rozwiązania tego typu. Ogólnie rzecz biorąc SVN zazwyczaj po prostu wystarcza. Wsparcie dla SVN możemy uzyskać w chyba każdym powszechnie używanym IDE, nawet jeśli nie ma go domyślnie, to poprzez wtyczki.

Tworzenie repozytorium

System SVN jest zorganizowany w strukturze klient-serwer. Na serwerze jest przechowywane tak zwane repozytorium, które zawiera wszystkie dane. Po stronie klienta jest tworzona jedynie tak zwana kopia robocza, czyli wycinek danego miejsca repozytorium oraz zadanej wersji - nie musimy pobierać całego repozytorium, może ono przechowywać wiele projektów, wiele gałęzi projektów - możemy pobrać tylko interesującą nas lokalizację. Do zarządzania systemem po stronie serwera służy program svnadmin. Najlepiej zacząć od wpisania polecenia:

svnadmin help

Dostaniemy listę wszystkich dostępnych komend. Wpisując dodatkowo na końcu jedną z nich program wypisze nam szczegółową pomoc dotyczącą tej komendy. Aby utworzyć repozytorium używamy komendy create oraz wskazujemy miejsce, gdzie chcemy utworzyć repozytorium. Ale uwaga - repozytorium, a nie nasz kod. Repozytorium to miejsce, gdzie serwer będzie magazynował dane, użytkownik zawsze pracuje na kopii roboczej (dane serwera są zapisane bazie danych więc to nie ważne, czy mamy repozytorium na tej samej maszynie, czy gdzieś indziej - i tak nie możemy edytować plików bezpośrednio w repozytorium). Powiedzmy, że utworzymy sobie repozytorium:

svnadmin create /home/wrzasq/svnrepo

Teraz, kiedy już mamy utworzone repozytorium tworzymy przypisaną do niego swoją kopię roboczą na której będziemy pracować. Robimy to poleceniem svn checkout (w skrócie svn co):

svn co file:///home/wrzasq/svnrepo/ /home/wrzasq/svnwork/

Polecenie to w praktyce utworzy nam katalog pusty (prawie) /home/wrzasq/svnwork/ z ukrytym katalogiem .svn, który zawiera dane dotyczące przypisanego repozytorium. Od tej pory wszystkie polecenia svn wykonywane w tym katalogu (i podkatalogach) będą się odnosiły do tej kopii roboczej (i wykonywane będą na przypisanym repozytorium).

Kontrola dostępu

Zanim zaczniemy pracę, przyda się jakoś skonfigurować nasze repozytorium, szczególnie pod kątem praw dostępu do niego. Jeśli pracujemy sami, a nikt inny do repozytorium nie ma dostępu to nie ma takiej potrzeby, ale dobrze wiedzieć jak to się robi. Konfiguracja repozytorium trzymana jest w podkatalogu conf w dwóch plikach:

  • svnserve.conf - to główny plik konfiguracji, tutaj w sekcji [general] ustawiamy jakie są zasady logowania. My chcemy, aby nikt niepowołany się do naszego repozytorium nie dostał:
    [general]
    # ta linijka ustala poziom dostępu dla anonimowych użytkowników
    anon-access = none
    # ta dla zalogowanych
    auth-access = write
    
    # w obu przypadkach dostępne są trzy opcje:
    # - none (brak dostępu)
    # - read (tylko do odczytu)
    # - write (pełny dostęp - odczyt i zapis)
    
    # nazwa pliku z hasłami użytkowników
    password-db = passwd
  • passwd - tutaj jest trzymana lista użytkowników oraz ich haseł w bardzo prostym formacie zwykłej listy (uwaga, hasła nie są w żaden sposób maskowane!).

Oprócz tego możemy poszczególnym użytkownikom ograniczyć dostęp do repozytorium definiując reguły w pliku wskazywanym przez parametr authz-db, ale nie zapędzajmy się. Ważne też, żeby pamiętać, że jest to konfiguracja serwera - my na razie pracujemy lokalnie (protokół file://), więc żadnych skutków tych ustawień nie odczujemy.

Dodawanie plików

Mamy już repozytorium i mamy już swoją kopię roboczą. Teraz czas wrzucić jakieś pliki. Praktycznie wszystkie operacje wykonujemy na swoim systemie plików - tworzymy pliki, edytujemy je, usuwamy. Kiedy już utworzymy pliki (powiedzmy pusty plik o nazwie test.php) dodajemy go do kontroli wersji poleceniem:

svn add test.php

Oczywiście w przypadku większych zmian takich plików będzie bardzo dużo - zamiast podawać nazwę pliku możemy wpisać gwiazdkę - svn add * doda nam wszystkie pliki włącznie z podkatalogami więc nie ma strachu. Teraz wpiszmy sobie coś do pliku (nie, nie jestem takim masochistą na codzień ;), chcę, żeby kod był prosty, ale żeby dało się go zmienić w kilku miejscach):

class HelloWorldClass
{
    const TEXT = 'Hello World!';

    public static function print()
    {
        echo '<p>', self::TEXT, '</p>';
    }
}

HelloWorldClass::print();

Aby zmiany zapisać w systemie musimy je zaksięgować. Robimy to komendą commit, w skrócie ci (program zapyta się o opis zmian - to zwykły tekst, który możemy wpisać, aby nie było w przyszłości problemów z połapaniem się "co autor miał na myśli" w ferworze zmian):

svn ci

W tym miejscu zaznaczę też, że system kontroli wersji działa na serwerze - zapisuje zmiany, które się do niego wysyła. Nie pamięta on każdego kliknięcia, każdego zmienionego znaku dopóki mu tej zmiany nie wyślemy, więc dopóki nie zaksięgujemy zmiany w systemie, nie mamy możliwości korzystania z tego systemu.

Możemy teraz wykonać svn co do innego katalogu i zobaczymy, że nasz plik został zapisany w repozytorium:

svn co file:///home/wrzasq/svnrepo/ /home/wrzasq/test/

Aby z kolei ściągnąć do swojej kopii roboczej zmiany naniesione w repozytorium przez innych użytkowników używamy polecenia update (w skrócie up).

Zarządzanie plikami

Zmiany w istniejących plikach będą wyłapywane przez system automatycznie. Inaczej sprawa się ma z samymi plikami - jeśli na przykład skopiujemy plik w swojej kopii roboczej, system nie będzie wiedział, że dany plik to kopia istniejącego już pliku, a szkoda tracić bardzo ważną funkcję SVN - potrafi on śledzić nie tylko zmiany w plikach, ale również same pliki (ich kopiowanie i zmianę nazwy). Polecenia SVN w tym zakresie są dość podobne do standardowych poleceń powłoki UNIX - cp służy do kopiowania, rm do usuwania, a mv do zmiany nazwy (przy czym ta ostatnia w przypadku SVN to po prostu wykonanie cp, a następnie usunięcie pierwowzoru. Spróbujmy zatem przetestować te możliwości kopiując test.php jako index.php:

svn cp test.php index.php

Powinniśmy dostać informację podobną do tej, jaka pojawia się po zwykłym dodaniu pliku, ale wcale nie było to zwykłe dodanie. Bardzo łatwo sprawdzić stan repozytorium poleceniem status (w skrócie st), które wypisuje wszystkie zmiany w obecnej kopii roboczej, które nie zostały zaksięgowane - powinno obok dodanego pliku wypisać znak +, co oznacza, że posiada on dodatkowe informacje dotyczące pierwowzoru:

svn st

Teraz skoro mamy drugi plik nie potrzebujemy pierwszego, więc go usuniemy:

svn rm test.php

Innymi dwoma przydatnymi poleceniami, które bardzo przydadzą się przy zarządzaniu plikami są polecenia dotyczące zmian w samych plikach. Pierwsze z nich, diff (w skrócie di) jak sama nazwa wskazuje wykonuje prace podobną do programu diff (a wręcz go używa) - pokazuje ono różnice między plikami. W przypadku SVN jednak główny sens nie polega na porównywaniu różnych plików, ale różnych wersji tego samego pliku, dlatego mamy możliwość podania jako parametrów wersji zadanych plików. W szczególnej (ale najbardziej przydatnej) wersji pokazuje ono zmiany naniesione w danym pliku w naszej kopii roboczej względem ostatniej zaksięgowanej zmiany - wpisanie w naszym przypadku:

svn di test.php

Wypisze nam cały plik, ponieważ w ostatniej zaksięgowanej zmianie ten plik istniał, a obecnie go usunęliśmy.

Drugie polecenie to cofanie naniesionych zmian. Polecenie to nazywa się revert (a nie ma skrótu :P). Jednak przez cofanie zmian nie rozumie się tutaj cofanie do innej wersji - cofa jedynie niezaksięgowane zmiany (przywraca najnowszą wersję), o przywracaniu innych wersji napiszę potem. Jeśli zatem chcemy odzyskać nasz plik, możemy użyć svn revert test.php (możemy też po prostu ściągnąć go z powrotem z repozytorium).

No to zapisujemy zmiany (svn ci) i idziemy do następnego punktu.

Gałęzie i tagi

W czasie rozwijania projektu nieraz przychodzi potrzeba rozwidlenia. Tagi (etykiety) to pewne zapisane wersje (zazwyczaj na takich zapisanych kopiach już się nie pracuje - stanowią one stały punkt dostępu na przykład do starszych wersji stabilnych). Gałęzie to odrębne strumienie rozwoju (czasem rozwijane jako alternatywa, a czasem jako po prostu wydzielona grupa zmian, po wykonaniu których zmiany zostaną wcielone do głównego drzewa). Nie będę się rozwodził nad organizacją repozytorium, nad organizacją samego projektu i tego typu zagadnieniami, więc załóżmy prosty przykład. Tworząc grę trzeba stworzyć nowy mechanizm do obsługi sieci, bo stary jest niewydajny. Praktycznie oznacza to konieczność napisania go od nowa. Gdyby zmiany na bieżąco nanosić na jedną i tę samą kopię, to aż do ukończenia prac nad nową obsługą sieci, cały program przestałby działać. Przydaje się więc stworzyć oddzielną kopię, gdzie odpowiedzialny za nią zespół będzie osobno pracował nad mechanizmami sieciowymi, podczas gdy główna gałąź (trunk) będzie oparty o stare, ale działające rozwiązania. Praktycznie osiąga się to przez zwykłe kopiowanie (svn cp) danego katalogu jako nowego. Jednak w praktyce przyjęło się stosować pewną konwencję, która określa strukturę katalogów trunk-tags-branches:

|-- trunk # to główna gałąź, czyli wersja podstawowa
|-- tags # zamrożone stany ważnych punktów
|   |-- ver2.2 # na przykład zapisana starsza wersja 2.2
|   `-- ver2.3 # i wersja 2.3
`-- branches # odrębne gałęzie rozwojowe
    |-- newnetwork # przykładowa gałąź do pracy nad nową obsługą sieci
    |-- newdb # nowa baza danych
    `-- newdb2 # alternatywna baza danych - po testach okaże się, która jest lepsza i ta zostanie wcielona do drzewa 'trunk'

Jednak jest to tylko (ale wolę o tym myśleć, jako "aż") konwencja i nie wprowadza żadnych systemowych zależności (chociaż wiele programów jest do niej przystosowanych i domyślnie takiej struktury używa, więc dobrze jest jej używać). My stworzymy sobie pseudo-gałąź jako po prostu osobny plik, powiedzmy, że nazwiemy go revindex.php:

svn cp index.php revindex.php

Wykonujemy svn ci i idziemy dalej.

Scalanie

Dochodzimy do najważniejszej chyba części jeśli chodzi o obsługę systemu wersji, czyli modyfikacja plików i ich scalanie. Żeby mieć jakieś podstawy do pracy wprowadźmy następujące zmiany do naszych plików (zaksięgujemy każdy plik osobno, a więc po edycji każdego pliku wykonajmy svn ci) - niech index.php zawiera (zmieniony tekst):

class HelloWorldClass
{
    const TEXT = 'Tutorial SVN - https://wrzasq.pl/';

    public static function print()
    {
        echo '<p>', self::TEXT, '</p>';
    }
}

HelloWorldClass::print();

svn ci i idziemy do revindex.php, gdzie zmienimy sposób wyświetlania:

class HelloWorldClass
{
    const TEXT = 'Hello World!';

    public static function print()
    {
        echo '<pre>', self::TEXT, '</pre>';
    }
}

HelloWorldClass::print();

Ponownie wykonujemy svn ci. Teraz mamy dwa pliki zawierające równoległe zmiany: w pierwszym zmieniliśmy treść, w drugim wygląd. Obie zmiany nam pasują, więc chcemy nanieść te z pliku revindex.php do oryginału. Do łączenia plików służy polecenie merge (nazwa również nieprzypadkowo taka sama jak program merge):

svn merge file:///home/wrzasq/svnrepo/revindex.php index.php

Jeśli teraz wykonamy svn di index.php zauważymy, że zmiana sposobu wyświetlania została naniesiona. Jeśli otworzymy plik zobaczymy również, że wyświetlana treść nie zmieniła się - nadal jest nowa. Teraz możemy już usunąć nasz plik "rozwojowy" revindex.php. Ale powiedzmy, że w pewnym momencie dochodzimy do wniosku, że jednak stary sposób był lepszy. Jak cofnąć zmiany już naniesione? W praktyce odbywa się to również przez scalanie, po prostu jako nośnik zmian podajemy starszą wersję. Jeśli wszystko robiłeś krok-po-kroku tak jak tu opisuję, to przed zmianą powinna być wersją 5 (a jeśli jednak coś majstrowałeś, to i tak nie powinno być problemu ze znalezieniem potrzebnej wersji - wiele informacji jest wypisywanych na ekran podczas pracy więc pewnie zauważyłeś jaki to był numer wersji - jeden mniejszy niż ta po poprzednim scaleniu). No więc tym razem wywołujemy merge, tyle, że podajemy dodatkowo numery wersji i to, co ważne, w odwrotnej kolejności (a potem już standardowo svn ci):

svn merge file:///home/wrzasq/svnrepo/index.php index.php -r 6:5

Jednak te zmiany nie były zbyt złożone, nie trzeba było oczywiście tworzyć dla nich osobnej "gałęzi" (że tak to dumnie w tym wypadku nazwę ;)). Jak już na początku wspomniałem sam system również śledzi zmiany, rozgałęzianie kodu ma sens, gdy nad jedną i tą samą rzeczą pracuje się na kilka sposobów, lub gdy nie chce się burzyć całego systemu. Aby zobaczyć jak sam system sobie radzi stwórzmy sobie drugą kopię roboczą:

svn co file:///home/wrzasq/svnrepo/ /home/wrzasq/svnwork2/

Ponownie wprowadźmy w dwóch plikach różne zmiany - w pliku /home/wrzasq/svnwork/index.php zapiszmy (zmienił się tekst wypisywany):

class HelloWorldClass
{
    const TEXT = 'Tutorial SVN - <a href="https://wrzasq.pl/" title="Wrzasq.pl - tworzenie storn i aplikacji internetowych.">https://wrzasq.pl/</a>';

    public static function print()
    {
        echo '<p>', self::TEXT, '</p>';
    }
}

HelloWorldClass::print();

Natomiast w pliku /home/wrzasq/svnwork2/index.php zapiszmy (zmiana nazwy klasy i metody):

class HelloWorld
{
    const TEXT = 'Tutorial SVN - https://wrzasq.pl/';

    public static function output()
    {
        echo '<p>', self::TEXT, '</p>';
    }
}

HelloWorld::output();

Jeśli teraz wykonamy svn ci w jednym z katalogów, to w drugim operacja ta będzie niemożliwa, ale bez paniki - to tylko zabezpieczenie. Aby mieć pewność, że zmiany nie nachodzą na siebie SVN nie pozwala przesyłać zmian dopóki nie uaktualni się swojej kopii roboczej do wersji z repozytorium. Wystarczy wykonać:

svn up && svn ci

Teraz w drugim katalogu również wykonujemy svn up. Możemy teraz sprawdzić - obydwa pliki są takie same, zawierają zmiany naniesione z obydwu źródeł. Czasem w tym wszystkim idzie się pogubić. Szczególnie jeśli pracuje się w zespole. Użyteczne w takiej sytuacji polecenie to blame - wypisuje ono informacje o zmianach konkretnych linijek (wraz z użytkownikiem wprowadzającym te zmiany) danego pliku:

svn blame index.php

Dobre nawyki

Jak zawsze oprócz ograniczeń technicznych, albo indywidualnych upodobań istnieją pewne zasady, których przyjęło się przestrzegać, lub po prostu dobrze jest się do nich stosować (na przykład ze względu na bezpieczeństwo danych). Wspominałem już chociażby o strukturze katalogów. Tak jak też napomknąłem, pracując z Subversion dobrze jest używać jego poleceń do chociażby przenoszenia plików, gdyż daje to możliwość dalszego śledzenia zmian. Dobrze jest też regularnie używać polecenia update, aby mieć pewność, że pracujemy na aktualnej wersji.

Logi

Inną bardzo ważną rzeczą jest tworzenie logów. Zapewne zauważyłeś, że przy każdym księgowaniu zmian system otwiera edytor i prosi cię o wpisanie opisu. Nawet jeśli używasz repozytorium samemu, warto wpisywać opis wprowadzanych zmian. Kiedyś ilość zmian w jednym pliku osiągnie nawet bardzo niewielką ilość - powiedzmy kilkanaście, możesz mieć problemy z określeniem, w którym miejscu konkretna zmiana miała miejsce, a teraz wyobraź sobie prace z ludzi, którzy jeszcze muszą to zgadywać w ciemno - ktoś kiedyś powiedział, że należy zawsze pisać tak, jakby ten kto ma potem utrzymywać kod był psychopatycznym mordercą znającym twój adres.

Dry-run

Uruchamianie "na sucho" jest szczególnie ważne w przypadku operacji merge - jeśli coś pójdzie nie tak jesteśmy, że tak powiem, w czarnej dupie. Zawsze dobrze jest najpierw użyć opcji "na sucho", czyli dodać do polecenia argument --dry-run - wypisze ona spodziewane rezultaty, ale nic nie zapisze na dysku. Tak, Subversion już dawno jest w fazie produkcyjnej, ale strzeżonego… wiecie.

Backup repozytorium

Skoro już mamy coś w repozytorium to szkoda, żeby kiedyś trafił to szlag. Na szczęście można zarzucać zawartość repozytorium i bezpiecznie przechowywać jego backup, ale aby się dobrać do samego repozytorium, będziemy musieli się posłużyć ponownie programem svnadmin. Do tworzenia zrzutu służy komenda dump - wypisuje ona zawartość wszystkich kolejnych wersji na standardowe wyjście, więc wystarczy przekierować jego strumień do pliku:

svnadmin dump /home/wrzasq/svnrepo/ > backup

Do odzyskiwania takiej kopii służy z kolei polecenie load. Skoro mamy kopię bezpieczeństwa, to możemy śmiało usunąć obecne repozytorium - usuwamy więc cały katalog /home/wrzasq/svnrepo/. Teraz stworzymy w jego miejsce puste repozytorium (polecenie jak na początku artykułu), a następnie wczytamy do niego zawartość pliku zrzutu - to polecenie z kolei sczytuje dane ze standardowego wejścia:

svnamdin load /home/wrzasq/svnrepo/ < backup

Przenoszenie katalogów

Czasami jednak dzieje się tak, że chcemy "wyciągnąć" historię jedynie jakiegoś wycinka repozytorium (chociażby żeby przenieść całą historię do innego repozytorium). Do tego trzeba zastosować osobny program - svndumpfilter, który filtruje zawartość zrzutu i wybiera jedynie pasujące elementy. Ponieważ użycie w praktyce w naszym przypadku wymagałoby zbyt dużego grzebania w naszym małym przykład pokażę jedynie przykłądowe zastosowanie:

svnadmin dump /home/wrzasq/svnrepo/ | svndumpfilter include projekt1 | svndumpfilter exclude projekt1/branches | svndumpfilter include projekt1/tags/test > backup

Polecenie to może wykluczać (exclude), albo wybierać (include) ścieżki ze zrzutu. Wypisuje ono dalej przefiltrowaną zawartośc, dlatego jak widać można takie filtry ze sobą łączyć. W tym wypadku filtr wybierze tylko katalog projekt1 z katalogu głównego, ale odrzuci jego dwa podkatalogi: branches i tags/test.

Udostępnianie repozytorium

Ostatnią przydatną umiejętnością jest udostępnianie repozytorium. SVN obsługuje wiele protokołów (chociażby HTTP korzystając z WebDAV, czy użycie SSH jako szyfrowania). Jednak żeby nie rozpisywać się zbytnio, ograniczę się do tego najbardziej podstawowego sposobu - odpalania zwykłego daemona. Wykorzystuje on protokół SVN (svn://). Domyślnie deamon pracuje na porcie 3690. Serwer uruchamiamy poleceniem svnserve. Musimy podać tryb pracy (jako argument) - mamy do wyboru tryb samodzielny (-d), tryb z użyciem super-serwera inet (-i), jako tunel (-t), lub w celach diagnostycznych tylko na jedno połączenie (-X). W sumie nas interesują tylko te dwa pierwsza, a żeby ułatwić sprawę, po prostu odpalimy serwer jako samodzielnego daemona, czyli opcja pierwsza. Jeśli uruchamiamy serwer w katalogu repozytorium, to svnserve -d w zupełności wystarczy. Możemy też uruchomić go z innego katalogu, podając lokalizację repozytorium jako parametr:

svnserve -d /home/wrzasq/svnserve/

Ta forma jest znacznie bardziej przydatna, chociażby przy tworzeniu skryptów uruchomieniowych. Oprócz tego możemy przy pomocy parametru --listen-port zmienić port, na którym nasz serwer będzie nasłuchiwał połączeń. Teraz inni nasi współpracownicy będą mogli się połączyć klientem SVN używając prostego URLa (względnie jeśli uruchamiasz serwer na innym porcie koniecznie będzie dodanie :port):

svn://twoj.adres.lub.domena/

Oprogramowanie

Ten tutorial opracowałem w oparciu o podstawowe oprogramowanie Subversion. Jest ono dostępne na chyba większość popularnych platform. Ale zapewne wielu ludzi odstrasza wizja korzystania z konsoli do każdej tego typu operacji - nic takiego, oczywiście istnieją graficzne oprogramowania klienckie. Większość z nich bardzo dobrze integruje się z powłoką systemową dzięki czemu praktycznie nie odczuwa się dodatkowego obciążenia w pracy z SVN, a jedynie korzysta z jego zalet. Wśród takich rozwiązań na pewno przoduje TortoiseSVN - klient pod Windowsa. Pod Linuksa bardzo wygodne jest KDE SVN. Oprócz tego tak jak wspominałem większość IDE posiada wsparcie dla różnego rodzaju systemów kontroli wersji, w tym dla SVN praktycznie większość - Eclipse, NetBeans, czy Visual Studio, dla pozostałych z pewnością też coś się znajdzie.

Tags: , , , ,