Bazaar uzupełnieniem SVN-a

Podziel się z innymi!

    Subversion – jeden model pracy
    =======================

    Najbardziej popularnym systemem wersjonowania jest [Subversion](http://subversion.tigris.org/). Został on zaprojektowany do pracy w sposób scentralizowany. Działa to tak, że gdzieś na serwerze znajduje się centralne repozytorium z którego programista pobiera kopię roboczą na swój lokalny komputer. Dokonuje modyfikacji plików po czym zatwierdza dokonane zmiany w repozytorium centralnym. Taki model pracy ma swoje zalety jednak zdarzają się sytuacje kiedy przydała by się lokalna wersja repozytorium. Poczciwy SVN nie daje jednak możliwości pracy w sposób rozproszony co jest jego wielką słabością w stosunku do np. [Gita](http://git-scm.com/) czy [Bazaar-a](http://bazaar.canonical.com/en/), które dzięki swojej elastycznej architekturze oferują wiele przeróżnych sposobów organizacji pracy z repozytorium.

    Modele pracy są jednym z wielu argumentów, dla których warto rozważyć przesiadkę na inny system kontroli wersji. Polecam zapoznać się z artykułami [Why Switch to Bazaar? – Any Workflow](http://doc.bazaar.canonical.com/migration/en/why-switch-to-bazaar.html#any-workflow) albo [Workflows – Bazaar Version Control](http://wiki.bazaar.canonical.com/Workflows) oraz [Why Git is Better than X – Any Workflow](http://whygitisbetterthanx.com/#any-workflow).

    Ja pracuję już kilka lat z Subversion i większość firm z którymi współpracuję lub też współpracowałem też używa SVN. Dlatego decyzja o zmianie systemu wersjonowania najczęściej nie leży w mojej gestii.

    Co mogę zatem zrobić? Zarówno Bazaar ([bzr-svn](https://launchpad.net/bzr-svn)) jak i Git ([git-svn](http://www.kernel.org/pub/software/scm/git/docs/git-svn.html)) mają narzędzia umożliwiające współpracę z Subversion.

    Po co łączyć Subversion z Bazaarem lub Gitem
    ==================================

    Model pracy rozproszonej oferuje kilka możliwości stanowiących doskonałe uzupełnienie modelu scentralizowanego.

    * Słabe połączenie internetowe albo jego brak nie jest problemem ponieważ wszelkie zmiany dokonywane są lokalnie. Połączenie z serwerem centralnym potrzebne jest jedynie raz na jakiś czas.
    * Niezależne repozytorium, odseparowane i nienarażone na zmiany czynione przez innych użytkowników daje możliwość eksperymentowania. Dokonane zmiany w przypadku powodzenia można później scalić z główną gałęzią lub też usunąć nie zaśmiecając historii zmian centralnego repozytorium.
    * Można ustalić procedurę zgodnie z którą zmiany dokonane w projekcie przez developera trafiają najpierw do osoby nadzorującej projekt, która je sprawdza, testuje i dopiero po akceptacji pcha da SVN-a. W ten sposób do centralnego repozytorium trafią jedynie zmiany stabilne.
    * Warto też wspomnieć o takim prozaicznym powodzie jak brak upierdliwych katalogów „.svn” w katalogu roboczym projektu – małe a cieszy :D.

    Praca z Bazaarem jako uzupełnieniem Subversion
    ======================================

    Importowanie repozytorium
    ————————–

    Ja wybrałem Bazaar z uwagi na moje większe doświadcznie z tym systemem kontroli wersji.

    Dla tych, którzy nie mieli jeszcze styczności z Bazaarem proponuję na start prosty tutorial [Bazaar in five minutes](http://doc.bazaar.canonical.com/bzr.2.1/en/mini-tutorial/index.html). Jeśli chodzi o naukę to Bazaar ma tę przewagę nad Gite, że większość jego komend jest identyczna z tymi znanymi z SVN.

    Jeśli nie mamy jeszcze zainstalowanego Bazaara (bzr) oraz wtyczki umożliwiającej współpracę z Subversion bzr-svn to w przypadku Ubuntu wystarczy jedynie pobrać wyżej wspomniane z repozytorium i zainstalować.

    sudo apt-get install bzr bzr-svn

    W przytoczonym wyżej tutorialu nowe repozytorium tworzy się poprzez komendę bzr init. W tym przypadku nie ma takiej potrzeby. Aby „zaimportować” repozytorium SVN do Bazaara należy utworzyć tzw. brancha. Zakładam że znajdujemy się w katalogu roboczym, w którym trzymamy projekty (workspace). Wywołujemy komendę bzr branch i podajemy jako parametry url repozytorium svn oraz nazwę katalogu jaki zostanie stworzony na naszym komputerze i w którym zostanie utworzone lokalne repozytorium Bazaara.

    bzr branch svn+http://svn-repository.example.com/project/trunk ./project

    Od tego momentu można już pracować z Bazaarem. Dostępna jest pełna historia zmian i jakby się uprzeć to można zapomnieć o SVN-ie 😉 (choć do właściwego importu SVN do Bazaar służy komenda bzr svn-import) Dostępne mamy zarówno narzędzia konsolowe, jak też całą kolekcję GUI z których niejako firmowym jest multoplatformowy [Bazaar Explorer](http://doc.bazaar.canonical.com/explorer/en/). Fanom Eclipse polecam z kolei [plugin do obsługi Bazaara](https://launchpad.net/bzr-eclipse), który niczym nie ustępuje swojemu odpowiednikowi dla Subversion.

    Pracujemy w ten sposób, że wszelkie zmiany w plikach zatwierdzamy (commit) do lokalnego repozytorium. Kiedy zmiany w projekcie przyjmują już stabilną postać jesteśmy gotowi do zarejestrowania wprowadzonych poprawek w centralnym repozytorium SVN. Zanim to jednak zrobimy należy najpierw sprawdzić czy od czasu ostatniego pobrania zmian z SVN coś się nie zmieniło. W końcu najczęściej nie pracujemy sami. Wchodzimy do katalogu naszego projektu i wywołujemy:

    Warto sprawdzić czy coś się zmieniło?
    ————————————

    bzr pull svn+http://svn-repository.example.com/project/trunk

    Jeśli pracujesz w zespole, a poprawka którą miałeś zrobić nie była mała to najprawdopodobniej otrzymasz komunikat, że w repozytorium dokonano zmian. Trzeba je będzie sprawdzić, scalić z lokalnymi zmianami i ponownie zatwierdzić. Bazaar podpowie Ci co masz zrobić.

    bzr: ERROR: These branches have diverged. Use the missing command to see how.
    Use the merge command to reconcile them.
    

    Scalanie różnic jest proste
    ————————-

    Jeśli inni developerzy nie edytowali tych samych plików co ty to zazwyczaj wystarczy:

    Do podejrzenia różnic

    bzr missing

    Do scalenia zmian

    bzr merge

    Następnie przydałoby się sprawdzić jakie pliki różnią się względem lokalnego repozytorium po scaleniu ze zmianami dokonanymi w repozytorium centralnym

    bzr status

    Po ich zatwierdzeniu

    bzr commit -m 'Treść komunikatu'

    Zostaje już tylko wysłanie wszystkiego do svn.
    ——————————————–

    bzr push svn+http://svn-repository.example.com/project/trunk

    UWAGA! append_revisions_only error
    ———————————–

    W tym momencie najprawdopodobniej wyskoczy Ci mały Zonk i otrzymasz taki niemiły komunikat

    Using saved push location: svn+http://svn-repository.example.com/project/trunk
    bzr: ERROR: Operation denied because it would change the mainline history. Set the append_revisions_only setting to False on branch "svn+http://svn-repository.example.com/project/trunk" to allow the mainline to change.
    

    Niestety komunikat Bazaar nie jest w tym wypadku wyczerpujący gdyż nic nie mówi na temat tego gdzie ustawić append_revisions_only na false.

    W Ubuntu wyedytuj plik ~/.bazaar/subversion.conf i dodaj wspomnianą dyrektywę pod adresem repozytorium SVN

    [4ef181b9-d188-42c4-ae88-58g6dfg8760b]
    locations = svn+http://svn-repository.example.com/project/trunk
    append_revisions_only = False
    

    To powinno załatwić sprawę.

    Uwaga konflikt!
    ————–

    To był optymistyczny scenariusz. W mniej pomyślnej sytuacji dokonasz zmian w tym samym pliku w którym ktoś inny grzebał i to najprawdopodobniej w tych samych liniach. Automat tego nie rozwiąże. Załóżmy, że chodzi o plik „foo.py”. Pojawia się konflikt a problematyczny plik doznaje cudownego rozmnożenia.

    1. foo.py.BASE – plik w wersji pozbawionej zmian powodujących konflikt (w svn foo.py.rOLDREV)
    2. foo.py.OTHER – plik ze zmianami dokonanymi przez innego użytkownika (w svn foo.py.rNEWREV)
    3. foo.py.THIS – plik z moimi lokalnymi zmianami (w svn foo.py.mine)
    4. foo.py – zawiera to samo co foo.py.THIS

    Kilka słów od Kdiff3 – bez niego moje życie było by o wiele bardziej skomplikowane
    ——————————————————————————

    Każdy ma swoje ulubione narzędzie do scalania różnic. Ja preferuję Kdiff3 – dostępny na Linuksa i Windowsa. Mimo, że zarówno Eclipse jak i Bazaar Explorer mają swoje narzędzia do porównywania zmian ja staram się użyć Kdiff3 którego interfejs jest mi dobrze znany.

    Edycja konfliktu przy użyciu Kdiff3 wymaga wywołania w konsoli komendy

    kdiff3 foo.py.BASE foo.py.OTHER foo.py.THIS -o foo.py

    Oczywiście nie wszyscy lubią konsolę. Aby np. Bazaar Explorer korzystał z Kdiff3 należy wyedytować plik ~/.bazaar/bazaar.conf i w sekcji DEFAULT dodać.

    external_merge = kdiff3 %b %o %t -o %r
    

    Jako ciekawostkę kierując się zawodową uprzejmością podaję też sposób wywołania tortoisemerge.

    external_merge = tortoisemerge /base:%b /theirs:%o /mine:%t /merged:%r
    

    Kdiff3 można też zintegrować z Eclipse jednak opcję taką znalazłem jedynie dla Subversion. Należy otworzyć Preferencje->Team->Diff/Merge. W sekcji „Conflict Resolution Program” wybrać opcję „External” i wskazać gdzie leży Kdiff3 (u mnie /usr/bin/kdiff3). W polu parameters należy podać

    ${base} ${yours} ${theirs}  -o ${merged}
    

    Rozwiązaniem konfliktu należy się pochwalić
    —————————————–

    Po ręcznym rozstrzygnięciu konfliktów należy Bazaar poinformować o tym – analogicznie jak w svn.

    bzr resolve foo.py

    Komenda „resolve” usuwa przy okazji pliki foo.py.BASE, foo.py.OTHER oraz foo.py.THIS. Teraz wystarczy już tylko zatwierdzić zmiany (commit) oraz pchnąć do centralnego repozytorium (push).

    Dobra rada na koniec
    ================

    Bazaar czy Git to systemy kontroli wersji stworzone do pracy rozproszonej oraz dopracowane pod kątem łączenia osobnych repozytoriów. Mają pod tym względem znaczną przewagę nad Subversion. Model pracy będący mixem korzystającym z rozproszonego repozytorium np. Bazaar oraz centralnego SVN ma swoje zalety jednak stanowi dodatkowy narzut pracy związany z koniecznością dublowania pewnych czynności. Nie należy na siłę wdrażać rozwiązań, które nie są efektywne lub wręcz zbędne. Dlatego jeśli w firmie używającej Subversion stosuje się dopracowane procedury zatwierdzania zmian w repozytorium, nie ma problemów z połączeniem, a modyfikacje w projekcie nie mają charakteru rewolucji będącej jednym wielkim eksperymentem wymagającym tworzenie piaskownicy, być może funkcjonalność Subversion jest w zupełności wystarczająca.

    Podziel się z innymi!

      3 Comments

      1. Scottie

        Świetny artykuł!

        PS Sam kiedyś stanąłem przed wyborem: Git, Bazaar, czy może Mercurial. Wybór padł właśnie na Bazaara głównie ze wzgl. na to, że jako jedyny oferuje pracę również z centralnym repozytorium. Co prawda Git jest bardziej popularny (ciekawe dlaczego?!), ale IMHO Bazaar jest lepszy.
        PPS Mercurial nie brałem pod uwagę, bo ma głupią nazwę 😉

      2. Zbigniew Heintze Post author

        Ja Mercuriala też nie miałem jeszcze okazji wypróbować, ale nie z powodu nazwy. Zresztą – wybacz – ale argument w stylu „głupia nazwa” zaliczam właśnie do głupich 🙂

      3. Scottie

        Heloooł! To był żart z tą nazwą (patrz emotikon na końcu zdania). Przed wyborem dokładnie poczytałem o wszystkich trzech i bzr jakoś najbardziej przypadł mi do gustu. Natomiast ciekawi mnie Twoje zdanie: ,,Ja wybrałem Bazaar z uwagi na moje większe doświadcznie z tym systemem kontroli wersji.” To doświadczenie musiało się jakoś zapoczątkować. Skąd u Ciebie Bazaar zamiast bardzo popularnego Gita?

      Dodaj komentarz

      Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *