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.

komentarze obsługiwane przez Disqus