Wersja 1.0 z dnia 21 maja 2006
System kontroli wersji?
Zapewne wiele razy podczas pracy z plikami chciałeś mieć możliwość przywrócenia jakiegoś z nich do stanu sprzed kilku dni czy tygodni, sprzed wielu zmian. Chciałeś też mieć możliwość zorientowania się, co i kiedy tak naprawdę zmieniłeś w swoim gąszczu plików. Albo też chciałeś mieć możliwość podzielenia się z kimś pracą bez konieczności żmudnego uzgadniania dokonanych zmian i uciążliwego dbania o to, abyście obaj (oboje) dysponowali zawsze najnowszymi wersjami efektów swojej pracy.
Jeśli jesteś programistą, z pewnością zetknąłeś się z systemami kontroli wersji. Ich zadaniem jest śledzenie zmian w kodzie źródłowym programów, co pozwala na przywracanie usuniętych fragmentów kodu czy łączenie elementów stworzonych przez różnych programistów, w różnym czasie. W odróżnieniu od zwykłych mechanizmów tworzenia kopii zapasowych (tzw. backupów), systemy kontroli wersji oferują znacznie większą funkcjonalność: możliwość odzyskania dowolnej wcześniejszej wersji danego pliku źródłowego, czy możliwość tworzenia gałęzi kodu i późniejszego ich łączenia. Bez takich mechanizmów praca nad rozbudowanymi projektami programistycznymi byłaby po prostu niemożliwa.
Do pewnego czasu najbardziej rozpowszechnionym systemem kontroli wersji był CVS, obecnie zastępowany przez nowszy i lepszy system Subversion (SVN), którego sam od kilku lat używam, i którego chciałbym polecić każdemu, kto regularnie pracuje z dowolnymi komputerowymi dokumentami.
Co prawda korzenie systemów kontroli wersji sięgają projektów programistycznych, nie oznacza to, że można ich używać tylko w tym celu. Subversion jest nowoczesnym oprogramowaniem opartym o otwarty kod źródłowy, który doskonale sobie radzi ze śledzeniem zmian w dokumentach rozmaitego rodzaju, nie tylko tekstowych, ale także binarnych. Pozwala właśnie na łatwe wykonywanie tych wszystkich operacji wymienionych na wstępie. To jest właśnie to.
Jak to działa?
Idea jest prosta. Gdzieś na dysku komputera lokalnego albo serwera znajduje się specjalna baza danych, tzw. repozytorium. W niej znajdują się nasze projekty wraz z historią zmian w nich dokonanych. My natomiast, już na naszym lokalnym dysku (to może być też ten sam dysk, na który jest repozytorium), mamy swój folder roboczy, który jest odzwierciedleniem części czy całości zawartości repozytorium. Folder roboczy tym się różni od każdego innego folderu, w którym trzymamy swoje pliki, że znajduje się w nim ukryte foldery o nazwie .svn zawierające dane niezbędne systemowi do śledzenia dokonywanych zmian. I cała zabawa polega na tym, aby cyklicznie uaktualniać dane przechowywane w repozytorium - dzięki temu będzie powstawać w nim cała historia zmian dokonywanych na plikach w naszym folderze roboczym.
Dzięki oprogramowaniu Subversion możemy obejrzeć historię zmian projektu, możemy "wyłuskać z niego" dowolną wcześniejszą wersję interesującego nas pliku, możemy skasować cały folder roboczy i odtworzyć go w najświeższym, czy dowolnym innym stanie. Możemy także dzielić się pracą z innymi i dzięki pośrednictwu wspólnego repozytorium przekazywać sobie wzajemnie pracę i uaktualniać nasze foldery robocze, aby zawierały zmiany dokonywane przez innych. Subversion daje nam możliwości niedostępne w zwykły sposób nawet dla najbardziej uważnego i porządnego użytkownika. Umieszczenie repozytorium na osobnym dysku czy serwerze zwiększa także bezpieczeństwo naszych danych. Mechanizmy kontroli wersji ułatwiają tworzenie kopii bezpieczeństwa, przygotowywanie pakietów do dystrybucji czy tworzenie kopii przyrostowych, które zawierają jednie zmienione pliki.
Subversion w praktyce
Subversion to nowoczesne, wieloplatformowe oprogramowanie, w swej podstawowej wersji przeznaczone raczej dla zaawansowanego użytkownika, bo wymagające posługiwania się linią komend. Czyli zdecydowanie nie dla każdego, jak sugeruje tytuł artykułu.
Nie jest jednak tak źle, gdyż właśnie dlatego, że mamy do czynienia z otwartym kodem źródłowym, system Subversion został przystosowany do korzystania przez każdego, czyli inaczej mówiąc, przez użytkownika systemu Windows. Wystarczy ściągnąć specjalną wersję programu - TortoiseSVN, która integruje się doskonale z eksploratorem Windows i pozwala nam korzystać z Subversion jak z każdego innego dobrego oprogramowania dla systemu Windows.
Po instalacji TortoiseSVN i ewentualnym restarcie systemu menu kontekstowe eksploratora, czyli to dostępne po kliknięciu prawym przyciskiem myszki na pliku czy folderze, udostępnia nam cały wachlarz poleceń programu TortoiseSVN, które są niczym innym, jak poleceniami systemu Subversion, ubranymi w przyjazny interfejs użytkownika.
W tym opisie będę posługiwał się angielskimi nazwami poleceń programu TortoiseSVN, bo taką wersję mam zainstalowaną i do takowej się przyzwyczaiłem, ale istnieje też wersja spolonizowana. Niezależnie od języka, sposób postępowania jest identyczny. Jako przykład zastosowania systemu kontroli wersji w codziennej pracy wybrałem sobie pliki z danymi do mojego bloga: kod PHP programu Wordpress, wersje HTML rozmaitych tekstów z mojej strony, pliki z obrazkami wykorzystywanymi przez stronę, oraz wszystkie inne pliki, które składają się na całość serwisu miasik.net. Czyli przykład będzie dla webmastera, ale zachęcam do dalszego czytania każdego, kto pracuje z dowolnymi komputerowymi dokumentami.
Rozpoczynamy zabawę od stworzenia repozytorium. W tym celu tworzymy folder, powiedzmy na dysku C:, o nazwie Repository (czyli C:\Repository\). Tam zostanie stworzona baza danych przechowująca i śledząca zmiany w naszych projektach roboczych. No, na początek w jednym projekcie, nazwanym miasik.net. Aby stworzyć repozytorium, używamy eksploratora, w którym wskazujemy na folder C:\Repository\ i klikamy prawym przyciskiem myszki. Z menu kontekstowego rozwijamy sekcję TortoiseSVN i wybieramy opcję Create repository here.
TortoiseSVN pyta nas jakiego rodzaju repozytorium ma stworzyć, gdzie do wyboru mamy 2 możliwości: prawdziwy system bazodanowy Berkeley Database (BDB) albo uproszczony system Native Filesystem (FSFS). Dla naszych potrzeb wystarczy opcja FSFS - jest efektywniejsza i mniej kłopotliwa.
Po chwili repozytorium jest gotowe i zostanie w nim stworzony cały zestaw folderów koniecznych do funkcjonowania bazy. Zawartość folderu C:\Repository\ przestaje nas od tego momentu interesować - jest on całkowicie obsługiwany przez system Subversion.
Mamy już repozytorium, ale jest ono puste - nie śledzi i przechowuje ono żadnych plików. Musimy je wypełnić naszym pierwszym projektem. W moim przypadku będzie to pełen zestaw plików składających się na moją witrynę miasik.net. Pliki te trzymam w folderze E:\Webdesign\miasik.net\. Aby znalazły się w repozytorium, muszą zostać do niego zaimportowane.
Operacja importu jest bardzo prosta - klikam prawym guzikiem na folderze z plikami mojego serwisu (E:\Webdesign\miasik.net\) i wybieram opcję TortoiseSVN zwaną, jakże by inaczej, Import.
Program pyta, do jakiego repozytorium chcę zaimportować wskazany folder, bo można mieć dowolną ilość repozytoriów umieszczonych w różnych miejscach. Tak przy okazji, to TortoiseSVN domaga podania adresu URL, co oznacza, że repozytoria mogą mieścić się w różnych miejscach, także na serwerach odległych, dostępnych przez internet. W naszym przypadku podajemy URL wskazujący na nasze lokalne, świeżo stworzone repozytorium (file:///C:/Repository/miasik.net/ - uwaga, w adresach URL używamy ukośników, a nie ukośników odwrotnych). Uwaga, ze względu na to, że chcemy obsługiwać tym samy repozytorium więcej projektów, adres URL zakończony jest częścią miasik.net, a więc wskazuje na coś w rodzaju podfolderu w repozytorium. Dzięki temu inne projekty będą mogły być umieszczane niezależnie od obecnego w tym samym repozytorium, każdy w osobnym podfolderze.
Po chwili import się kończy bardzo znaczącym komunikatem określającym aktualny numer rewizji po zakończonej operacji. Na początku wynosi on 1 i jest zwiększany po każdej operacji zmieniające stan repozytorium. W zasadzie repozytorium jest takim składowiskiem, w którym struktura naszego projektu, czyli pliki i foldery, jest powielana za każdą operacją, która coś w niej zmienia i każda taka powielona "kopia" otrzymuje nowy numer rewizji. Oczywiście nie oznacza to, że w bazie za każdym razem wykonana jest kompletna kopia wszystkich plików i folderów - system zapamiętuje jedynie to, co się zmieniło, na dodatek stosując bardzo efektywny system kodowania zmian. Dzięki temu wiele rewizji projektów zawierających pliki binarne nie powoduje gwałtownego rozrostu rozmiarów repozytorium. Niemniej jednak, z naszego punktu widzenia każda rewizja to kompletny zestaw plików składających się na projekt w danym momencie.
Teraz musimy stworzyć sobie folder roboczy (kopię roboczą), tym razem będący już pod kontrolą systemu Subversion. Oczywiście robimy sobie kopie bezpieczeństwa folderu E:\Webdesign\miasik.net\, a następnie czyścimy jego zawartość. Teraz klikamy na nim prawym przyciskiem i z menu kontekstowego wybieramy opcję SVN Checkout, która służy właśnie do pierwszego pobrania zawartości repozytorium do jakiegoś folderu roboczego.
W opcji SVN Checkout podajemy adres repozytorium i interesującego nas folderu z projektem w repozytorium, oraz ścieżkę do folderu na dysku lokalnym, w którym ma pojawić się zaadresowana zawartość - czyli do folderu roboczego.
Po zakończeniu operacji otrzymujemy komunikat, że nasz folder roboczy został stworzony, czyli zakończyła się operacja SVN Checkout. Dowiadujemy się też, jaki jest numer rewizji stworzonej przez nas kopii roboczej. W naszym przykładzie jest to rewizja 1, czyli dokładnie taka sama, jak ta, która została przed chwilą zaimportowana.
TortoiseSVN dodaje do eksploratora dodatkową własność, a mianowicie oznacza w specyficzny sposób ikony plików i folderów, które kontroluje. Pozwala to łatwo oceniać stan dokonanych lokalnie zmian w kopii roboczej. Dzięki tym dodatkowym elementom ikon łatwo nam zorientować się, które fragmenty projektu zostały właśnie zmienione. Początkowo wszystkie ikony mają nałożony zielony "ptaszek" oznaczający, że pliki są w najbardziej aktualnym, nie zmienionym stanie, odpowiadającym temu w repozytorium.
Poniżej jest sytuacja, w której jeden z plików został zmieniony. Czerwony wykrzyknik jasno wskazuje w którym folderze dokonano zmiany
Przeglądanie tak oznaczonych folderów prowadzi do konkretnego zmodyfikowanego pliku: index.php. Wykrzyknik oznacza, że dany plik w kopii roboczej został zmieniony i nie odpowiada już temu, co zapamiętane jest w repozytorium.
W tym przypadku zmiana była świadoma i chcemy, aby repozytorium zostało o tym fakcie powiadomione. W takim wypadku musimy zatwierdzić i "wysłać" nasze zmiany do repozytorium używając operacji SVN Commit. Zaznaczamy konkretny plik lub folder ze zmianami, wywołujemy menu kontekstowe i wybieramy odpowiednią opcję.
Pojawia się okno wyświetlające listę zmienionych plików - możemy zawsze zadecydować, że nie chcemy jeszcze wysyłać wszystkich zmian. W naszym wypadku jednak chcemy wysłać zaznaczony plik. Dodatkowo możemy naszą zmianę opatrzyć komentarzem, który może być nam bardzo pomocny za jakiś czas (czy też przyda się innym osobom pracującym razem z nami nad tym projektem).
Potwierdzamy wprowadzone operacje przyciskiem i po chwili mamy komunikat o zakończonym procesie wysyłania zmian do repozytorium. Oprócz tego dowiadujemy się, że nasza kopia robocza ma obecnie rewizję 2. Znów wszystkie pliki oznaczone są zielonymi ptaszkami.
Po tej operacji w repozytorium znajduje się rewizja 1 zawierająca początkowy stan zawartości mojej witryny oraz rewizja 2 zawierająca wszystkie pliki w stanie niezmienionym plus jeden plik zmodyfikowany (index.php). Tak właśnie działa mechanizm pozwalający na powrót do dowolnego stanu naszego projekt. Czyż to nie wspaniałe? Oczywiście w repozytorium nie ma dwukrotnie powielonej zawartości - to nie ma sensu w przypadku, gdy zmieniliśmy jeden plik. To Subversion dba o to, abyśmy niezależnie od tego, o którą rewizję pytamy, otrzymali wszystko, co do niej należy.
Teraz cały cykl pracy polega na tym, że dokonujemy jakichś zmian, a następnie poprzez operację SVN Commit informujemy repozytorium o dokonanych modyfikacjach. A każda zmiana tworzy nową rewizję, do której możemy się w razie potrzeby odwołać. Tak, to takie proste.
I nie ma znaczenia, czy zarządzamy w ten sposób plikami źródłowymi programów, dokumentami pakietu Office, plikami z grafiką, czy czymkolwiek innym - dla systemu Subversion to bez różnicy. Oczywiście w przypadku dokumentów tekstowych mamy znacznie większe możliwości analizowania zmian, gdyż możemy wyszukiwać modyfikacje nie tylko na poziomie plików, ale także ich zawartości, co nie jest możliwe w przypadku plików binarnych. Możemy śledzić zmiany dowolnych plików, nad którymi regularnie pracujemy, bez względu na to, czemu służą. Subversion to naprawdę system dla każdego.
Subversion przy współpracy
System kontroli wersji jest nieoceniony w sytuacji, gdy nad projektem pracuje więcej niż jedna osoba jednocześnie. Dzięki niemu można zapewnić wymianę dokonywanych zmian pomiędzy współpracownikami i zabezpiecza on, do pewnego stopnia, przed wzajemnym "psuciem" sobie dokonanych modyfikacji.
Zacznijmy może od prostego przykładu współpracy, na razie w ramach sieci lokalnej. Powiedzmy, że ja się zajmuję modyfikacjami szaty graficznej swojej witryny, a moja żona dokonuje konstruuje jakąś sprytną wtyczkę do programu WordPress, który "napędza" moją stronę (dobra, wiem, że to bardzo wydumana sytuacja). Początek operacji wygląda identycznie, czyli każde z nas na swoim komputerze tworzy kopię roboczą z tego samego repozytorium, umieszczonego gdzieś w folderze dostępnym z obu komputerów.
Mając kopie robocze dokonujemy jednocześnie zmian w swoich częściach projektu. Po dokonanych zmianach każde z nas wysyła je do repozytorium używając opcji SVN Commit. Widzimy, że zmieniają się numery rewizji, czasem szybciej, co sugeruje, że nie tylko jedna osoba dokonuje zmian. Problem jednak w tym, że po pewnym czasie oboje będziemy mieć różne kopie robocze, bo zawierające tylko nasze własne modyfikacje. A na dodatek każda z nich będzie różna od tego, co znajduje się w repozytorium, bo przecież każde z nas ma jedynie swoje modyfikacje. Subversion nie może nas zmusić do uaktualnienia naszej kopii roboczej - system uaktywnia się jedynie wtedy, gdy my tego chcemy.
W takiej sytuacji, musimy poprosić Subversion o uaktualnienie naszej kopii roboczej do wersji zgodnej z zawartością najświeższej rewizji (zwanej HEAD) z repozytorium. Używamy do tego opcji SVN Update, która "nanosi" na naszą kopię roboczą wszystkie zmiany dokonane przez drugą osobę. Aktualizację dokonujemy na całym folderze roboczym, albo jedynie na tej części, w której spodziewamy się zmian.
Subversion sprawdza, które pliki w repozytorium zostały zmodyfikowane, dodane lub usunięte, i nanosi stosowne zmiany w naszej kopii roboczej, uaktualniając jej rewizję do najnowszej.
Przy współpracy cykl operacji dla każdej osoby wygląda mniej więcej tak:
- Robimy SVN Update - aby mieć najbardziej aktualną wersję.
- Dokonujemy modyfikacji lokalnych.
- Robimy SVN Commit, aby nasze zmiany powędrowały do repozytorium.
- Powtarzamy cykl od punktu 1.
Jak łatwo zauważyć, nie musimy w tym celu zupełnie porozumiewać się z drugą osobą. Całą sprawę załatwia za nas Subversion, my jedynie oglądamy w oknach komunikatów, co tam nowego się pojawiło w naszym wspólnym projekcie. Jeśli oboje posługujemy się tym cyklem, system dba, abyśmy maksymalnie szybko otrzymywali wzajemnie dokonywane zmiany.
Oczywiście w praktyce współpraca bywa znacznie bardziej skomplikowana, ale używanie Subversion jest niezbędne, aby ilość problemów będących efektem tej komplikacji została zredukowana do minimum. Ale to już zadanie dla zaawansowanych użytkowników. Czyli nie dla każdego.
Podsumowanie
Mam nadzieję, że ten krótki i wstępny opis jest dostatecznie zachęcający przynajmniej do spróbowania zabawy z kontrolą wersji i z Subversion. Zalety płynące z używania tego narzędzia są tak duże, że nie wyobrażam sobie żadnej poważnej pracy bez niego. Oczywiście program narzuca pewne, czasem odrobinę bardziej uciążliwe schematy pracy, ale płynące z tego korzyści są tego warte. Warto też wgłębić się w inne możliwości oferowane przez system kontroli wersji, bo to jest narzędzie, którego celem jest ułatwianie nam życia.
Inne przydatne operacje Subversion
Subversion pozwala nam prześledzić historię operacji na dowolnym pliku, który kontroluje. W moim przypadku użyłem na pliku index.php operacji Show log i otrzymałem krótką historię zmian tego pliku: dodanie go do repozytorium w rewizji 1 oraz modyfikację w rewizji 2 (ze stosownym komentarzem). Historia daje nam dostęp do innych ciekawych funkcji: anulowania dokonanych zmian, wyciągania starszych wersji plików, odnajdywania plików, które już nie są częścią kopii roboczej (zostały kiedyś usunięte). Otwierają się nowe możliwości, zupełnie niedostępne przy normalnej pracy z plikami i kopiami zapasowymi.
Dodanie nowych plików w kopii roboczej nie oznacza, że automatycznie zostaną one poddane kontroli systemu. Aby Subversion zaczął śledzić dany plik musi on zostać dodany do kopii roboczej. Wystarczy kliknąć prawym przyciskiem na pliku i wybrać opcję Add. Od tej chwili plik zostaje oznaczony jako "przynależny" do kopii roboczej, niemniej jednak nie został jeszcze umieszczony w repozytorium. Dopiero wykonanie operacji SVN Commit powoduje, że plik powędruje do repozytorium i stanie się pełnoprawnym elementem projektu.
Trzeba pamiętać, że wiele operacji na kopii roboczej trzeba wykonywać za pośrednictwem programu TortoiseSVN - np. kasowanie plików czy zmiany ich nazw. Używanie do tego po prostu Windows doprowadzi do utraty synchronizacji pomiędzy repozytorium a folderem roboczym. Usunięcie pliku w "normalny" sposób nie usuwa go z repozytorium i przy najbliższej operacji SVN Update taki skasowany plik zostanie przywrócony z repozytorium. Oczywiście taka operacja bywa czasem przydatna - jeśli napsujemy coś w pliku w nieodwracalny sposób, to wystarczy go skasować i użyć opcji SVN Update na danym folderze, aby TortoiseSVN przywrócił nam ostatnią wersję pliku z repozytorium.
Jeśli nasze repozytorium zawiera wiele projektów, a na wielu nie prowadzimy bieżących prac, nie musimy przechowywać ich folderów roboczych. W razie konieczności możemy użyć opcji SVN Checkout do ponownego stworzenia kopii roboczej. Jeśli projekt ma rozbudowaną strukturę, a potrzebujemy doraźnie coś poprawić w jednym elemencie struktury (np. pliku), to nie musimy pobierać z repozytorium całej struktury projektu. Folderem roboczym może być dowolny zagnieżdżony fragment struktury zapisanej w repozytorium. W takim wypadku pobieramy jedynie interesujący nad fragment (wraz z podfolderami) do wybranego folderu i pracujemy nad nim w identyczny sposób, jak z dowolną większą częścią projektu. Takie postępowanie może nam znacznie uprościć pracę nad dużymi plikami, które jedynie okazjonalnie zostają pobrane z repozytorium. Takie system pracy jest ułatwiony, gdy budujemy strukturę opartą o wiele folderów z niewielkimi zagnieżdżeniami (poziomą), gdyż Subversion nie pozwala na wyciągnięcie z repozytorium pojedynczego pliku, a jedynie całe foldery.
Bywa, że nasze projekty zawierają pliki, których nie chcemy śledzić i przechowywać w repozytorium - no przykład rozmaite pliki tymczasowe. TortoiseSVN pozwala takie pliki oznaczyć jako ignorowane i wtedy system będzie je po prostu ignorował.
W dowolnym momencie możemy z repozytorium ściągnąć dowolną rewizję w "czystej" formie, pozbawionej dodatkowych informacji przechowywanej w ukrytych folderach .svn. Służy do tego operacja Export. Podajemy w niej URL projektu (lub dowolnego fragmentu drzewa folderów zapamiętanego w repozytorium), folder docelowy, rewizję i po chwili mamy w tym folderze odtworzoną strukturę i zawartość wybranej rewizji. I możemy ją umieścić np. na serwerze WWW, czy wysłać komuś, bez obciążania ją sporo ilością dodatkowych danych używanych przez system Subversion.