Mercurial - rozproszone zarządzanie wersjami na przykładzie
Poniższy artykuł to uzupełnienie do ogólnego wprowadzenia do rozproszonego zarządzania wersjami - przykład, jak wyglądają komendy Mercuriala i jak mogą być używane w zespole.
Niechże będzie sobie zespół złożony z Ani, Pawła, Michała i paru innych osób.
Daję niżej przykłady komend wydawanych z linii poleceń. Są one wygodne i najlepiej demonstrują działanie programu, ale można oczywiście używać także interfejsów graficznych. Choćby TortoiseHG albo merclipse.
Wczesne fazy projektu
Michał zaczyna nowy projekt:
michal$ hg init ~/src/supersklep
i dokonuje pierwszych edycji:
michal$ cd ~/src/supersklep # ... hack hack michal$ hg add readme.txt testing.txt michal$ hg ci -m "Wstępne założenia projektu" # ... hack hack michal$ hg add sql/ michal$ hg ci -m "Pierwsza wersja schematu bazy danych" michal$ mkdir doc michal$ hg mv *.txt doc/ michal$ hg ci -m "Przeniesienie dokumentacji do katalogu doc"
Do projektu dołącza Ania, która ma zrobić parę mockupów wyglądu. Rzecz nie ma jeszcze formalnego głównego repozytorium, dlatego po prostu pobiera projekt od Michała:
ania$ hg clone ssh://michal.firma.local/src/supersklep requesting all changes adding changesets adding manifests adding file changes added 3 changesets with 7 changes to 4 files updating working directory 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
albo i tak:
michal$ cd ~/src/supersklep michal$ hg serve --port 9977 ania$ hg clone http://michal.firma.local:9977 ~/supersklep ...
(jeszcze inna opcja to spakowanie zmian komendą bundle i przesłanie ich np. mailem)
Oboje sobie pracują, regularnie commitując a okazyjnie pobierając od siebie nawzajem swoje zmiany, np:
ania$ cd ~/supersklep ania$ hg pull http://michal.firma.local:9977 pulling from http://micha.firma.local:9997 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)
Informacja o powstaniu nowego rozgałęzienia jest normalna, oznacza, że i Michał i Ania commitowali zmiany od poprzedniej synchronizacji. Widząc ją Ania robi:
ania$ hg merge 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) ania$ hg commit -m "merge"
W rzadkich wypadkach wystąpienia prawdziwego konfliktu (oboje edytowali ten sam plik i to w tym samym miejscu) uruchomiony zostaje graficzny program do mergeowania (np. kdiff3 albo meld) i osoba robiąca merge wybiera, czyją wersję wykorzystać (albo edytuje dany fragment w zupełnie nowy sposób).
Ponieważ kombinacja pull, merge i commit jest częsta, można korzystać i z wygodnego skrótowca robiącego te trzy rzeczy razem:
ania$ hg fetch http://michal.firma.local:9977
Wreszcie, pisanie pełnych adresów jest męczące, zamiast tego można:
michal$ cd ~/src/supersklep michal$ hg pull ania
gdzie ania jest symbolem wpisanym przez Michała do pliku ~/src/supersklep/.hg/hgrc, który wygląda jakoś tak:
[paths] ania = ssh://ania.firma.local/supersklep
Codzienne zwykłe operacje
Zwykłe operacje wyglądają znajomo dla użytkownika dowolnego systemu zarządzania wersjami:
$ hg add util.hxx util.cxx $ hg rm wvgh.php $ hg mv draft.txt readme.txt $ hg commit -m "Fix #74344 (błędy kompilacji na RH)" $ hg log $ hg diff -r 97 tests $ hg annotate Makefile
Miłe jest, że działają nawet na laptopie bez sieci.
Drobna pułapka: wszystkie polecenia obejmują domyślnie cały katalog roboczy (a nie, jak to jest w wielu narzędziach, podkatalogi katalogu roboczego). Innymi słowy:
$ hg commit
(bez parametrów) działa dokładnie tak samo, czy jesteśmy w ~/src/superprojekt/, ~/src/superprojekt/sql/, czy może ~/src/superprojekt/pages/core/auth/. Dotyczy to także innych poleceń. Działanie tu i w głąb dostajemy podając kropkę jako parametr, np:
$ hg commit .
Gdy się już przywyknie, jest to bardzo wygodne.
Zaczynamy formalizować
Po paru dniach pracy widać, że projekt faktycznie ruszy. Dostaje więc swoje oficjalne gniazdko. Zakłada je (np.) Michał:
michal$ hg clone ~/src/supersklep ssh://repo.firma.local//projects/supersklep
Ania i Michał robią sobie w .hg/hgrc alias do głównego repozytorium (może być po SSH, może być po HTTP/DAV jeśli administrator woli to konfigurować w ten sposób) i od tego czasu pracują trochę inaczej. Nie wymieniają się już bezpośrednio (z wyjątkiem specyficznych przypadków typu przejrzyj ten kawałek zanim oddam do oficjalnego repozytorium) ale synchronizują się z głównym serwerem.
Pobranie nowych zmian od innych członków zespołu:
michal$ hg fetch serwer
Wrzucenie własnych zmian na główny serwer, by inni je zobaczyli:
michal$ hg push serwer
Do projektu dołączają kolejne osoby, inicjując swoje repozytoria przez:
pawel$ hg clone://repo.firma.local//projects/supersklep
Pojawiają się pierwsze kamienie milowe, oznaczane tagami:
michal$ hg tag sklep-0.1.0
Dużo dużo później
Gdy projekt urośnie, dzielonych repozytoriów robi się więcej. Np. może się pojawić:
ssh://repo.firma.local//projects/supersklep-staging
przeznaczone do szykowania oficjalnych dystrybucji, czy:
ssh://repo.firma.local//projects/supersklep-1.0
w którym są poprawiane błędy w starej wersji, gdy trwa już rozwój następnej.
Zaczynają być stosowane uprawnienia, nie każdy ma prawo zrobić push do tych repozytoriów.
Z drugiej strony, pojawiają się wypustki pozwalające na niezależne rozwijanie potencjalnie inwazyjnych zmian, np.:
ssh://repo.firma.local//branches/supersklep-csslayout
przez pewien czas rozwijane na boku bez umieszczania zmian w głównym repozytorium developerskim. Synchronizacja następuje dopiero, gdy cała duża reorganizacja kodu jest gotowa.
Zaczynają się przydawać polecenia takie jak bisect (szukanie od której wersji pojawił się jakiś błąd), annotate (kto i kiedy napisał ten fragment), view (graficzny podgląd historii) albo glog (tekstowa wizualizacja rozgałęzień i połączeń).
Itd itp.