Współpracę z Subversion, z powodu popularności tego projektu, uważam za najważniejszą funkcję wszystkich innych systemów kontroli kodu. Rozproszone systemy kontroli kodu mają wiele zalet; polecam wykład Linusa Torvaldsa na ten temat. Nawet jeżeli uważasz, że jest lekko skrzywiony w stronę Gita, i tak warto posłuchać jego argumentów dotyczących rozproszej kontroli kodu.
Biorąc pod uwagę popularność Subversion, typowy scenariusz użycia polegałby na użyciu rozproszonego systemu kontroli wersji, użyciu go do wyciągnięcia kodu z Subversion, pracy z wieloma prywatnymi gałęziami, a na koniec przesłaniu zmian z powrotem na serwer Subversion.
Istnieje wiele rozproszonych systemów kontroli wersji, chciałbym przetestować wszystkie, ale mając ograniczoną ilość czasu, przetestowałem tylko Bazaar i Git.
Ten tutorial jest inspirowany znakomitym Git-SVN Crash Course.
W Bazaar, drzewo katalogów jest gałęzią. W Gicie, jest to raczej gałęźnik, czyli zasobnik na gałęzie. Ta różnica prowadzi do wielu różnic w użyciu tych programów. Na przykład, jeżeli chcesz stworzyć nową gałąź Bazaar, musisz stworzyć nowe drzewo katalogów na dysku. Jeżeli używasz Gita, możesz zrobić to samo w istniejącym katalogu.
Bazaar jest prosty: ponieważ można mieć tylko jedną gałąź kodu w jednym drzewie katalogów, wystarczy sama nazwa katalogu żeby pchać, ciągnąć i łączyć kod. W przypadku Gita, jest to bardziej skomplikowane, ponieważ musisz albo określać gałąź o którą ci chodzi, albo gałąź ta jest wybierana domyślnie, na przykład „bieżąca gałąź”.
Widzę tutaj dwa spore punkty na korzyść Bazaar. Pierwszy jest taki, że
Git musi być zainstalowany na zdalnym serwerze. Jeżeli akurat używasz
Dreamhosta, musisz zrobić własną instalację Gita; skompilować go,
zainstalować w $HOME/bin
, ustawić $PATH
itd. Są też
inne sposoby, ale nie zmienia to faktu
że jeżeli spróbujesz po prostu pchnąć kod na
ssh://example.com/katalog
, dostaniesz błąd.
Jeżeli nagle pojawi się potrzeba wrzuceniu repozytorium Git na inny serwer,
musisz powtarzać całą operację. Bazaar potrafi czytać i kod ze zdalnych
serwerów przez ssh (sftp), nie wymagając przy tym zdalnej instalacji
Bazaar. Bardzo wygodne.
Drugi punkt dla Bazaar to tworzenie zdalnego repozytorium. Używając
Bazar, możesz po prostu podać nowy URL, dodać opcję --create-prefix
i gotowe. Git wymaga zalogowania się na zdalny serwer, gdzie trzeba
ręcznie stworzyć repozytorium.
Podczas klonowania repozytoriów Git, metadane Subversion są pomijane;
nie można sklonować repozytorium Git, a potem pchnąć kod do Subversion
z nowego repozytorium. Innymi słowy, można przesyłać dane z powrotem do
Subversion tylko z miejsca w którym się te dane wyciągało (przy pomocy
git-svn
).
W przeciwieństwie do Gita, Bazaar potrafi pchać zmiany do Subversion z dowolnej gałęzi. Można wyciąganąć kod z Subversion, potem go rozgałęzić, w nowej gałęzi wprowadzić własne zmiany i wrzucić je do Subversion.
Ten tutorial został napisany przy użyciu Git 1.5.2.1 i Bazaar 0.17.0.
Uruchomienie obydwu na jednym komputerze nie jest zbyt proste w momencie pisania tego tutoriala. Współpraca z Subversion wymaga nowej jej wersji. Nie mogłem jej łatwo zainstalować, bo nie było jej w Gentoo Portage. Ubuntu Feisty Fawn ma załataną wersję Subversion, ale ma z kolei Gita 1.4, który sporo różni się od 1.5. Innymi „słowy”:
Gentoo 2007.0 | Ubuntu 7.04 | |
---|---|---|
Subversion | 1.3 (za stary) | 1.3 załatany |
Git | 1.5 | 1.4 |
Pod Gentoo, można zainstalować Subversion 1.4, dodając flagę ~x86
do
/etc/portage/package.keywords
.
Ja zrobiłem inaczej: skompilowałem Gita 1.5 ze źródeł pod Ubuntu 7.04.
Można też tak jak podpowiada i0:
pod Feistym można zainstalować Git 1.5 z backportowego repozytorium deb-src Gutsy’ego, służy do tego Prevu — buduje pakiety (także dla starszych wersji Ubuntu), które można zainstalować z lokalnego repozytorium.
Kod łączący Bazaar i Subversion w Ubuntu jest instalowany razem z samym Bazaar; w przypadku innych dystrybucji może być potrzebne zainstalowanie osobnego pakietu.
Żeby przerobić całość tego tutoriala, musisz mieć dostęp do zapisu w jakimś repozytorium Subversion. Jeżeli nie masz możliwości zapisu w żadnym repozytorium Subversion, nie będziesz w stanie przesłać z powrotem swojego kodu, co z jednej strony jest całym sensem tego tutoriala, ale z drugiej strony ten tutorial będzie równie pomocy osobom które chcą wziąć kod z jakiegoś projektu, powiedzmy na Sourceforge, i się nim pobawić. To było najdłuższe zdanie z tego tutoriala. Jeżeli je przeczytałeś, najgorsze masz już za sobą.
Powiedzmy że masz standardowy, zalecany układ repozytorium Subversion z katalogami trunk, branches i tags.
. |-- branches |-- tags `-- trunk
Możesz zaimportować wszystkie gałęzie (branches) i tagi do Gita, ale do Bazaar możesz zaimportować tylko trunk, stąd url/trunk.
git-svn clone -T trunk -b branches -t tags url |
bzr branch url/trunk |
Możesz wyedytować jakiś plik. Kiedy skończysz, musisz zatwierdzić (commit) swoje zmiany. Tutaj dochodzimy do pierwszej różnicy pomiędzy scentralizowanym i rozproszonym systemem kontroli kodu: tutaj nie zatwierdza się przesyłając dane do serwera, wszystko dzieje się lokalnie.
git commit -a | bzr commit |
git-svn dcommit | bzr push url/trunk |
Może się zdarzyć, że ktoś w międzyczasie prześle zmiany do głównego repozytorium Subversion. Nie możesz po prostu zatwierdzić (commit) swoich zmian, bo… już je zatwierdziłeś! Do swojego lokalnego repozytorium. A ponieważ ktoś zatwierdził swoje zmiany w centralnym repozytorium Subversion, gałęzie te się rozszczepiły. Musisz je połączyć.
Łączenie zmian w Gicie czy Bazaar wygląda mocno inaczej niż to z czym mamy do czynienia w Subversion. Nie trzeba pamiętać żadnych numerów wersji. Nie trzeba się w ogóle martwić całym tym badziewiem, ani spędzać nad tym połowy dnia. Można po prostu połączyć zmiany.
Jest też różnica pomiędzy Git i Bazaar w łączeniu. W Bazaar, łączy się
zmiany z Subversion z gałęzią, w jednym kroku. W Gicie potrzeba dwóch
kroków. Najpierw uaktualnia się zdalną gałąź, nazwaną trunk
,
a następnie połączyć zmiany z tego trunk
z bieżącą gałęzią. Druga
różnica jest taka, że w Bazaar, po złączeniu, trzeba jeszcze zatwierdzić
zmiany. W Gicie, o ile nie było konfliktów, nie ma takiej potrzeby.
git-svn fetch | bzr merge url/trunk |
git merge remotes/trunk |
W tym momencie, ponieważ łączysz zmiany, możesz napotkać konflikty w kodzie. Rozwiązanie ich należy do ciebie. Git ma coś co się nazywa git-mergetool. Narzędzie to używa domyślnie Emacsa. Jeżeli chcesz, możesz poprosić je o użycie Vima.
git-mergetool -t vimdiff | bzr resolve file |
git commit -a | bzr commit |
Teraz masz już złączone zmiany ze zdalnej gałęzi, konflikty rozwiązane i zatwierdzone. Uprzednio rozwidlone gałęzie są z powrotem połączone. Można pchnąć zmiany na serwer.
git-svn dcommit | bzr push url/trunk |
Dla Gita oznacza to coś trochę innego niż dla Bazaar. Używając Gita, tworzy się nową gałąź w tym samym drzewie katalogów; w Bazaar tworzy się nowe drzewo.
git checkout -b branch |
bzr branch file:///path new-path |
Zarówno w Git jak i w Bazaar, łączenie odbywa się poprzez „ciągnięcie” (w przeciwieństwie do pchania) zmian.
git merge branch |
bzr merge url |
bzr commit |
Jeżeli chcesz przenosić kod pomiędzy kilkoma komputerami, możesz użyć
„gwizdka” USB. Konwencja nazw *.git
służy do oznaczania tzw. „gołych”
repozytoriów.
git clone --bare path /media/Pendrive/my-project.git |
bzr push file:///new-path --create-prefix |
Tutaj, path oznacza ścieżkę do drzewa katalogów ze źródłami. Jest
jeszcze jedna różnica pomiędzy Git i Bazaar; Git nie posiada opcji
--create-prefix
. Jeżeli chcesz utworzyć nowe drzewo katalogów na
gwizdku, musisz użyć funkcji clone
, która oznacza raczej ciągnięcie
niż pchanie.
Możesz później sklonować repozytorium z gwizdka na lokalny dysk na innym komputerze.
git clone /media/Pendrive/my-project.git my-project |
bzr branch file:///media/Pendrive/my-project |
Gwizdek USB mi nie wystarcza; często chcę przesyłać zmiany przez sieć. Stosunkowo łatwe rozwiązanie polega na użyciu serwera na którym ma się konto z dostępem przez ssh. Jeżeli masz zainstalowany sshfs, możesz podmontować zdalny katalog i używać go tak jakby był lokalny.
sshfs -C user@example.com:/home/user ~/foo \ -o idmap=user -o workaround=rename \ -o uid=$UID -o gid=$(id -g) |
Nie pytajcie mnie o te dziwne opcje. One są po to żeby naprawić jakiś problem z czymś, rozpracowałem to już jakiś czas temu i wszystkie informacje na ten temat zostały już wypłukane przez strumień artykułów z reddit.com na temat Haskella.
Jeżeli używasz Bazaar, przesyłanie przez sieć jest łatwiejsze. Możesz po prostu:
bzr push sftp://user@example.com/home/user/my-project \--create-prefix |
Opcja --create-prefix
jest potrzebna tylko za pierwszym razem. Później
można:
bzr push sftp://user@example.com/home/user/my-project |
Przepraszam za brzydkie słowo powyżej.
Ten tutorial jest tylko przejściem przez kilka podstawowych funkcji Git i Bazaar; w żaden sposób nie wyczerpuje tematu. Wszelkie sugestie są mile widziane. Możesz do mnie napisać na:
python -c "print 'bWFjaWVqLmJsaXppbnNraUBnbWFpbC5jb20='.decode('base64')"
Copyright© 2007 Maciej Bliziński.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.
Last modified on Mon Dec 17 23:24:07 +0000 2007.