Mercurial

Z funus.net

Mercurial to system kontroli wersji, zajmujący wraz z gitem miejsce w czołówce otwartoźródlanych narzędzi tego typu.

Do 2011 roku byłem użytkownikiem Subversion, całkiem przyzwoitego i stabilnego narzędzia pracującego w modelu scentralizowanego. Po pewnym jednak czasie nie daje się nie zauważyć jego niedogodności. Gdy wypróbowałem Mercuriala, prędko się przekonałem o jego zaletach i wyższości nad SVN-em. Dlatego w zastosowaniach prywatnych przeszedłem stopniowo na Hg, konwertując do niego chyba wszystkie moje repozytoria.

Spis treści

[edytuj] Do zainstalowania

Uwaga. Żeby działało polecenie hg view, trzeba po instalacji Mercuriala ręcznie dokopiować skrypt contrib/hgk.

[edytuj] Instalacja ze źródeł

Ostatnio instalowałem tak:

python setup.py build
python setup.py install --prefix=/usr/local --root=/usr/local/stow/mercurial-1.9.x

Wydaje się, że alternatywnie można posłużyć się dostarczonymi Makefile'ami:

make install PREFIX=/user/local DESTDIR=/usr/local/stow/mercurial-1.9.x

Testy modułowe:

make check

[edytuj] Rozszerzenia

Rdzeń Mercuriala jest całkiem funkcjonalny, niemniej istnieje cały szereg rozszerzeń dostarczających dodatkowych, mniej lub bardziej pożytecznych funkcji. Część z nich jest "oficjalna" i dystrybuowana wraz z samym Mercurialem, ale domyślnie nie są aktywne. Żeby takie rozszerzenie włączyć, należy umieścić w pliku konfiguracyjnym wpis podobny do następującego:

[extensions]
rebase =

To spowoduje aktywację rozszerzenia Rebase. W przypadku rozszerzeń nie dołączonych "fabrycznie" do Mercuriala, należy podać po znaku = ścieżkę do rozszerzenia, np.:

[extensions]
hgsubversion = ~/hg-extensions/hgsubversion/hgsubversion

Pracując z Mercurialem znalazłem szereg rozszerzeń, które dziś uznaję za niemal niezbędne. Są to:

  • bookmarks – zakładki przypominające nieco branche w stylu gita
  • convert – konwersja pomiędzy różnymi typami repozytoriów
  • graphlog – asciiartowy graf obok loga
  • hglock – lockowanie plików w rozproszonym systemie kontroli oprogramowanie jest na pozór mało sensownym pomysłem, ale...
  • hgsubversion – konwersja z Subversion bądź używanie Mercuriala w ograniczonym zakresie jako klienta SVN
  • mq – Mercurial Queues czyli kolejki patchy, niezwykle przydatne narzędzie
  • rebase
  • transplant – przenoszenie poszczególnych changesetów między branchami, odpowiednik git cherry-pick czy svn merge

Też fajne, choć można się bez nich obejść:

  • color – koloryzuje na terminalu standardowe wyjście niektórych poleceń (np. log, diff)
  • fetch – pull + update + merge + commit
  • hgk – prymitywne gui wywoływane poleceniem hg view
  • pager – przydatne gdy tekst nie mieści się na ekranie...
  • progress, czyli pasek postępu przy niektórych poleceniach command line
  • purge – czyści przestrzeń roboczą z niepotrzebnych plików
  • record – pozwala interaktywnie wybrać zmiany do skomitowania

Inne ciekawie wyglądające rozszerzenia, pewnie się nimi pobawię niedługo:

[edytuj] Współpraca z Subversion

Do dyspozycji mamy jednorazową konwersję z repozytorium SVN przy pomocy standardowego rozszerzenia convert. Ale co jeśli nie jesteśmy gotowi na tak rewolucyjną zmianę? Jest kilka narzędzi umożliwiających traktowanie repozytorium SVN jako głównego, czy inaczej: używanie Mercuriala w roli klienta Subversion. Żadne z nich nie działa jednak wystarczająco dobrze jak na moje potrzeby.

Zobacz też: Working with Subversion

[edytuj] Konwersja

Przy pomocy standardowego rozszerzenia convert.

[edytuj] HgSubversion

Funkcjonalność pozwlająca na korzystanie (clone, push, pull) z repozytoriów subversion byłaby czymś nieocenionym przy próbach przejścia z svn na hg. Rozszerzenie HgSubversion byłoby strzełem w dziesiątkę, ale niestety, w praktyce działa tylko z niewielkimi repozytoriami, o niezbyt skomplikowanej historii. Warto jednak popróbować, a nuż się uda.

Ma dwa tryby pracy: klonowanie całego repozytorium SVN bądź tylko wybranego podkatalogu (np. trunk czy jakiś branch). Pierwsza metoda wymaga "standardowej" struktury (trunk, branches, tags). Testowałem to pobieżnie na dość dużym repozytorium o nie do końca takiej strukturze i nie udało się, po kilku tysiącach wywalił jakiś błąd. Z kolei konwersja jedynie tranka się powiodła, ale nie wiem, czy tak to ma faktycznie działać: próba dociągnięcia nowych zmian przez hg pull, bez modyfikowania czegokolwiek w klonie mercurialowym, powoduje utworzenie jakby nowej gałęzi o tej samej nazwie i potem mercurial chce mi je merge'ować dająć jakieś konflikty...

Pomocne materiały na wiki Mercuriala:

[edytuj] hgsvn

hgsvn to nierozwijany już od jakiegoś czasu zestaw skryptów pełniących podobną rolę jako rozszerzenie HgSubversion. Niedawno (w wakacje 2011) pojawił się jakiś bugfix, ale jak zaznacza autor - tylko naprawdę krytyczne błędy będą poprawiane.

[edytuj] Branche

Koncept branchy jako równoległych linii developmentu jest różnie realizowany w różnych systemach, a nawet w ramach jednego może być osiągnięty na różne sposoby. W przypadku Mercuriala mamy co najmniej 4 możliwości:

  • sklonowanie repozytorium; branch w postaci klona oznacza separację na tak długo, jak nam się podoba, ale wadą, szczególnie przy dużych projektach, jest większe zużycie przestrzeni dyskowej
  • w repozytorium pojawiają się spontaniczne rozgałęzienia spowodowane przez changesety posiadające te same parenty, niezależnie od tego, czy changesety te powstały w tym samym repozytorium, czy w różnych; rozgałęzienia te na ogół są merge'owane prędzej czy później
  • nazwane branche, które w zasadzie są etykietami na stałe przypisywanymi do poszczególnych changesetów oraz ich childów, jednak ich zmiana w kopii roboczej wymusi powstanie rozgałęzienia; należy zwrócić uwagę, że to bardzo "ciężka" odmiana branchy, każdy changeset będzie na zawsze przypisany do jakiegoś nazwanego brancha (domyślnie default) i przypisanie to będzie się propagować na wszystkie klonowane repozytoria
  • bookmarks, czyli nazwane wskaźniki przesuwające się wraz z comittami na danej linii developmentu; to mercurialowa odpowiedź na koncepcję branchy w gicie. Podstawowa wada: nowo dodane bookmarki nie propagują się pomiędzy repozytoriami podczas operacji pull i push; trzeba je jednorazowo przepchać jawnie (pull/push -B nazwa); potem będą już aktualizowane automatycznie.

[edytuj] Uwagi

  • Napisany w pythonie, co ma swoje zalety i wady.
  • Podobnie jak Subversion czy git, nie zwraca uwagi na prawa dostępu (mode) plików, z wyjątkiem flagi executable. Może to mieć znaczenie w zastosowaniach takich, jak wersjonowanie katalogu /etc.
  • Wygląda na to, że git ma zdecydowanie aktywniejszy development i chyba też większą bazę użytkowników.
  • Wersja 1.9 ma bug w poleceniu hg verify, powodujący wyświetlanie następującego komunikatu: "0: changeset refers to unknown manifest 000000000000" w repozytoriach stworzonych przez polecenie hg convert. Nie należy się tym przejmować. [3]. Poprawiono w 1.9.1.
  • Mercurial nie interesuje się szczególnie katalogami w kontekście innym, niż wersjonowanie zawartych w nich plików. W konsekwencji nie da się zapamiętać w repozytorium pustych katalogów, co w niektórych zastosowaniach będzie upierdliwością.

[edytuj] Kto używa

  • Mozilla (Firefox i inne produkty) [4]
  • Python (ostateczna konwersja z subversion w marcu 2011) [5]
  • Netbeans (prawie 200k changesetów) [6]
  • Xen (przynajmniej częściowo) [7]
  • OpenSolaris [8]
  • OpenJDK [9]
  • GMP, The Gnu Multiple Precision Arithmetic Library [10] [hgweb]

Zobacz też: lista projektów używających Mercuriala

[edytuj] Konfiguracja

Pluginowata architektura Mercuriala staje się po pewnym czasie ciut irytująca, w szczególności gdy chcemy z niego korzystać na różnych maszynach i z różnych kont. Na ten drugi przypadek pomóc może stworzenie globalnego, systemowego pliku konfiguracyjnego /etc/mercurial/hgrc, który u mnie wygląda następująco:

[extensions]
color           =
convert         =
eol             =
extdiff         =
fetch           =
graphlog        =
#hgsubversion   =
hgk             =
rebase          =
mq              =
pager           =
progress        =
purge           =
record          =
transplant      =
 
[pager]
pager           = less -SFRX
attend          = diff glog help log qdiff incoming outgoing status
 
[extdiff]
kompare         =
kdiff3          =
 
# for TortoiseHg:
%include        /usr/local/opt/thg-and-stuff/thg/contrib/mergetools.rc

[edytuj] Zobacz też