System kontroli wersji (w skrócie VCS) jest to oprogramowanie, które służy do współdzielenia i śledzenia zmian w plikach oraz pomocy w łączeniu zmian pochodzących z różnych źródeł. W każdym, nawet najmniejszym projekcie, gdzie kilka osób pracuje równolegle nad tymi samymi plikami, niezbędne jest miejsce gdzie wszystkie te zmiany się spotykają – tutaj właśnie do gry wchodzi repozytorium kodu. Nawet jeżeli pracujemy sami, to powinniśmy się zastanowić czy nie chcielibyśmy skorzystać z możliwości śledzenia zmian jakie daje nam VCS. W tym tekście postaram się przedstawić pokrótce ewolucję systemów VCS i możliwości coraz bardziej popularnego w ostatnim czasie Git’a.
Żaden współczesny zespół programistów nie może obyć się bez systemu kontroli wersji. Pamiętam jak na studiach, w jakimś na szybko robionym projekcie próbowaliśmy obyć się bez tego narzędzia i było nam dość ciężko. Nawet pomimo tego, ze był to zespół zaledwie 3 osobowy… Trudno było stwierdzić, która wersja pliku jest najnowsza, co w pliku ostatnio się zmieniło i kto to zrobił, nie mówiąc już o łączeniu zmian. System kontroli wersji rozwiązuje większość problemów, z którymi się wtedy borykaliśmy. Oczywiście VCS nie jest lekarstwem na wszystkie bolączki związane z pracą grupową. Nie da się w codziennej pracy uniknąć konfliktów przy łączeniu równolegle wykonywanych zmian. Jeżeli w codziennej pracy doświadczamy wielu takich sytuacji, to najprawdopodobniej znaczy to, że nasz system jest słabo podzielony na moduły i żadne narzędzia kontroli wersji ani rozwiązywania konfliktów nam tutaj nie pomogą – chociaż niektóre VCS są tu bardziej pomocne niż inne.
Był CVS…
Historia systemów kontroli wersji sięga lat 70-tych, ale pierwszym powszechnie używanym systemem był CVS (Concurrent Versions System), który powstał w latach 90-tych i jest rozpowszechniany na licencji GPL. Jest to system pracujący w architekturze klient-serwer, wciąż utrzymywany, ale już nie rozwijany. Pewnie część z Was ominęła „przyjemność” pracy z CVS’em – chyba nie ma czego żałować. Linus Torvalds (tak, ten on Linux’a i Git’a) twierdzi, że znacznie lepszym rozwiązaniem niż CVS’a są pliki z patchami…
Do największych wad CVS’a według mnie należy brak możliwości wersjonowania katalogów i nietransakcyjność commit’ów, która może prowadzić do utraty synchronizacji pomiędzy kopią lokalną a repozytorium.
Zostawmy w takim razie CVS’a i przenieśmy się do XXI wieku.
Jest SVN…
SVN jest obecnie podstawowym systemem kontroli wersji stosowanym w wielu firmach. Został zaprojektowany jako następca CVS i tak samo jak on jest systemem pracującym w architekturze klient-serwer. Głównym założeniem przy tworzeniu SVN’a było pozbycie się największych błędów CVS’a. Trzeba przyznać – niezbyt ambitny cel…
Główne zalety SVN’a w stosunku do CVS’a to przede wszystkim transakcyjność commit’ów, możliwość wersjonowania katalogów i obsługa kopiowania plików (wreszcie pliki nie pojawiają się znikąd) oraz natywne wsparcie dla plików binarnych – dokładne porównanie różnych VCS można znaleźć tutaj.
Do zalet SVN’a można także bez wątpienia zaliczyć jego dojrzałość i dostępność różnorakich narzędzi pomagających w codziennej pracy, takich jak TortoiseSVN (klient SVN) czy Subclipse (plugin do obsługi SVN w Eclipse).
Główną wadą SVN’a, którą odziedziczył po CVS’ie, jest jego centralizacja. Można sobie wyobrazić jakie konsekwencje to za sobą pociąga. Brak backupu historii (no ale przecież każda firma robi regularne backupy SVN’a – prawda?). Każda operacja wykonywana na repozytorium wymaga komunikacji sieciowej, co spowalnia komunikację, a kiedy sieć „padnie”, to praca z repozytorium jest niemożliwa…
Będzie Git!
Sytuacja ma się zupełnie inaczej w przypadku Git’a. Linus Torvalds twierdzi, że jego głównym założeniem przy projektowaniu Git’a było WWCVSND, czyli What Would CVS Not Do. Linus tak samo jak CVS’a szczerze nienawidzi także SVN’a – przy rozwoju jądra Linux nigdy nie używał żadnego z nich.
W pierwszej kolejności trzeba powiedzieć, że Git jest systemem rozproszonym.
Wynika z tego pierwsza wielka zaleta tego systemu – może on pracować offline – bez połączenia z głównym repozytorium. Umożliwia to nam przeglądanie historii i lokalne commit’owanie zmian! Jest to niezwykle przydatne gdy chcemy pracować bez dostępu do firmowej sieci, lub gdy chcemy zapisywać wyniki naszej pracy, ale jeszcze nie jesteśmy gotowi, żeby umieścić je w głównym repozytorium. Praca offline owocuje także bardzo szybkim działaniem systemu.
Architektura Git’a pozwala na używanie repozytorium w zupełnie inny sposób niż do tego przywykliśmy pracując z SVN’em.
Schemat scentralizowany – oczywiście jest możliwe używanie Git’a w sposób do którego przywykliśmy używając SVN’a, czyli ze scentralizowanym repozytorium, do którego wszyscy mają prawo zapisywać zmiany. Ale to jest nudne…
Schemat z managerem integracji – to już brzmi lepiej – bardziej profesjonalnie… A o co chodzi? Każdy developer umieszcza zmiany w swoim publicznym repozytorium, po czym wyznaczony „manager integracji” wybiera pożądane zmiany i integruje je w głównym repozytorium projektu. Programiści powinni odświeżyć swoje kopie lokalne z głównego repozytorium projektu. Daje nam to już jakiś obraz możliwości jakie niesie ze sobą praca z Git’em, ale najlepsze właśnie przed nami.
Dictator and Lieutenants Workflow– rozwinięcie poprzedniego schematu – bardzo interesujące rozwiązanie gdzie tworzony jest łańcuch odpowiedzialności w oparciu o który można budować strukturę zaufanych źródeł. Pozwala on zorganizować pracę w ten sposób, że programiści commit’ują swoją pracę do repozytorium „porucznika” (osoby wyznaczone do przeglądu i akceptacji kodu) a dopiero oni, jako osoby bardziej zaufane, mogą commitować kod do głównego repozytorium projektu, z którego programiści mogą uaktualniać swoje kopie lokalne. Schemat bardzo użyteczny w bardzo dużych projektach (używany jest np. przy pracach nad jądrem systemu Linux) lub w organizacjach o wielowarstwowej strukturze (np. outsourcujące część prac).
Krótki przegląd możliwości Git’a w tym względzie znajdziemy w książce Pro Git dostępnej online.
Kolejną zaletą na którą zwraca szczególną uwagę Linus Torvalds jest kryptograficzna autentykacja historii. Historia commit’ów w repozytorium jest przechowywana w taki sposób, że nazwa konkretnej wersji zależy od całej historii prowadzącej do tej wersji (używany jest algorytm SHA-1). Po opublikowaniu wersji niemożliwe jest niezauważalne zmienienie historii.
Do popularyzacji Git’a w ostatnim czasie bez wątpienia przyczynił się założony w 2008 roku github. Jest to darmowe (dla projektów opensource) ogólnodostępne repozytorium Git, z którego korzystają takie projekty jak Rails, JQuery czy Mootools.
Git jako klient SVN?
Dobra wiadomość dla osób „uwięzionych” w korporacyjnym świecie SVN’a – Git’owcem można zostać nawet jeżeli oficjalnie używanym w projekcie repozytorium jest SVN! Tworzymy w takiej sytuacji swoje lokalne repozytorium Git będące kopią repozytorium SVN (z całą historią) i możemy korzystać ze wszystkich dobrodziejstw Git’a. Od tej chwili możemy commit’ować zmiany do lokalnego repozytorium (nie musimy do tego celu instalować żadnego serwera) i synchronizować jego zawartość z repozytorium SVN w dogodnym momencie. Pozwala to np. na pracę bez dostępu do sieci albo zebranie kilku commit’ów w lokalnej kopii i zsynchronizowanie ich z repozytorium SVN w dogodnym momencie. Jest to trochę podobne do zapisywania swoich zmian w osobnym branch’u w repozytorium SVN z tą tylko różnicą, że nie musimy tego robić! Nie musimy tworzyć zbędnych gałęzi w repozytorium – robimy wszystko lokalnie, dzięki czemu jest o wiele szybciej i łatwiej.
Ale po kolei. Najpierw inicjujemy lokalne repozytorium (znowu posłużymy się przykładem biblioteki Apache Commmons Lang):
[crayon lang=”bash”]
$ git svn init http://svn.apache.org/repos/asf/commons/proper/lang/trunk
[/crayon]
Ta operacja powinna zająć nie więcej niż kilka sekund. Zainicjowaliśmy repozytorium Git – na razie powstał tylko katalog .git. Teraz musimy się zdecydować od jakiej wersji chcemy skopiować historię repozytorium SVN. Oczywiście im więcej wersji spróbujemy pobrać, tym więcej czasu to zajmie. Ja zdecydowałem się na wersję 1148152 sprzed 4 miesięcy:
[crayon lang=”bash”]
$ git svn fetch -r1148152
$ git svn fetch
[/crayon]
To zajmie nam już trochę więcej czasu, ale znacząco przyspieszy pracę z historią w przyszłości. Spróbujcie sami:
[crayon lang=”bash”]
$ git log
[/crayon]
Od tej chwili możemy korzystać z naszego własnego repozytorium Git. To znaczy między innymi, że możemy zacommitować do niego zmiany:
[crayon lang=”bash”]
$ git commit -a -m „nasz pierwszy commit”
[/crayon]
Mamy pierwszy Git’owy commit za sobą. Oczywiście nie zapisaliśmy jeszcze tych zmian w repozytorium SVN. Żeby to zrobić używamy komendy:
[crayon lang=”bash”]
$ git svn dcommit
[/crayon]
Komenda ta przeniesie wszystkie wcześniej zacommitowane w lokalnym repozytorium Git zmiany do SVN’a – jako osobne wersje, jedna po drugiej – bardzo przyjemny widok ;)
Dobra wiadomość dla uczulonych na konsolę – częścią dystrybucji Git’a jest proste ale poręczne GUI. Wystarczy w konsoli wpisać git gui. Jeżeli używacie Eclipse’a to także mam dla Was dobrą wiadomość – istnieje EGit – plugin, który umożliwia integrację Git’a z Eclips’em.
To Git or not to Git?
Podsumowując, chciałbym was gorąco zachęcić do zostania Git’owcem i korzystania z jego udogodnień. Może na początku nie uda Wam się przekonać kolegów i kierownika, ale jak widać wcale nie trzeba – możecie zacząć od siebie.
Zachęcam także bardzo do obejrzenia prezentacji na temat Git’a, którą wygłosił sam autor Linus Torvalds, a którą posiłkowałem się podczas pisania:
Całkiem niedawno pojawiła się nowa opcja migracji z Svn na Gita – nazywa się SubGit: http://subgit.com
Jest to rozwiązanie, które stawia się na serwerze Subversion. Dzięki temu ludzie, którzy chcą używać Git’a używają go normalnie (bez komend git-svn), a kawałek serwerowy zapewnia synchronizację z repozytorium SVN.
Nie próbowałem tego jeszcze ale brzmi fajnie. Warto by było wytestować.
Pojawił się super fajny tutorial o Mercurialu (innym popularnym DVCS, konkurencyjnym do gita): http://hginit.com/ napisany przez Joela Spolsky’ego – polecam.
Dla ludzi pracujących z svn jest tam fajna część „Subversion Re-education”. Ogólnie może być przydatna nie tylko do pracy z Mercurialem, ale do DVCS ogólnie.