Najlepsze praktyki
Wskazówki jak efektywniej używać Subversion.
W tym rozdziale, skupimy się na omówieniu kilku pułapek systemów
kontroli wersji w ogólności, a Subversion w szczególności.
Powiemy także, jak je omijać.
Formatowanie kodu źródłowego
Subversion porównuje i łączy pliki tekstowe linia po linii. Nie rozumie
składni języków programowania, nawet nie domyśli się, że tekst został
przeformatowany z inną długością linii.
Biorąc to pod uwagę, ważnym jest by unikać niepotrzebnego reformatowania.
Tworzy to zbędne konflikty w czasie łączenia gałęzi, aktualizacji
kopii roboczych, czy też aplikowania patchy. Może także utopić w szumie
w czasie rozpatrywania różnic między poszczególnymi wersjami.
Tych problemów można uniknąć przez wprowadzenie i przestrzeganie
jasno zdefiniowanych reguł formatowania. Dokument HACKING projektu
Subversion (http://svn.collab.net/repos/svn/trunk/HACKING)
oraz Reguły Formatowania dla Języka Java (Code Conventions for the Java Programming Language;
http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html),
są dobrymi przykładami
(Warto też zajrzeć pod http://www.doc.ic.ac.uk/lab/cplus/c++.rules/
--tłum).
Szczególnie ważnym punktem są tabulacje. Niektóre projekty, jak
Subversion, w ogóle nie używają tabulacji w kodzie źródłowym. Inne używają
ich zawsze, a nawet szczegółowo definiują jej rozmiar.
Nieoceniony może stać się edytor, który jest na tyle inteligentny,
by wspomagać dotrzymywania tychże reguł.
Na przykład vim potrafi to zrobić, rozdzielając
reguły wg. projektu przy pomocy .vimrc
jak np.:
autocmd BufRead,BufNewFile */rapidsvn/*.{cpp,h}
setlocal ts=4 noexpandtab
autocmd BufRead,BufNewFile */subversion/*.[ch]
setlocal sw=2 expandtab cinoptions=>2sn-s{s^-s:s
Sprawdź dokumentację swojego ulubionego edytora, może i on to potrafi.
Gdy musisz reformatować
W prawdziwym świecie, nic nie jest doskonałe. Formatowanie może
się z czasem zmienić, albo po prostu zrobimy błąd. Są jednak czynności,
które możesz wykonać by zminimalizować problem reformatowania.
Te wskazówki warte są rozpatrzenia:
Jeśli dokonujesz rozległych zmian w formatowaniu (np. dostosowując
kod do innych reguł formatowania), zrób to w pojedynczym zatwierdzeniu
bez jakichkolwiek zmian semantycznych. Podaj szczegółowe wskazówki,
jak zduplikować zmiany w formatowaniu.
Jeśli dokonałeś zmian semantycznych w pewnej części kodu i
dostrzegasz nieścisłości formatowania w przyległym kontekście,
przeformatuj go. W tym przypadku konflikty spowodowane reformatowaniem
nie są tak znaczące, gdyż i tak zmiany semantyczne pewnie je spowodują.
Oto jeden z przykładów takich rozległych zmian:
$ svn co file:///repo/path/trunk indent_wc
$ indent -gnu indent_wc/src/*.[ch]
$ svn commit -m 'Ran indent -gnu src/*.[ch]' indent_wc
Zmiana ta przestrzega wszystkich powyższych reguł: braku zmian
semantycznych (żaden z plików nie zmienił się inaczej niż
poprzez zastosowanie polecenia indent.
Wywołanie polecenia podano wraz z parametrami, więc zmiany
te mogą łatwo zostać zduplikowane) oraz wszystkie zmiany zostały wprowadzone
w pojedynczej wersji.
Powiedzmy, że zmiany te zostały wprowadzone w wersji 26 głównej
linii kodu (trunk). Główna wersja (head) nosi teraz numer 42.
W wersji 13 stworzono gałąź (branch), którą teraz chcemy dołączyć
do głównej linii kodu. Normalnie robi się to poprzez:
$ svn co file://repo/path/trunk merge_wc
$ svn merge -r 13:head file://repo/path/branches/mybranch merge_wc
… # resolve conflicts
$ svn commit -m 'Merged branch'
Jednak zmiany w formatowaniu powodują, nieskończoną liczbę
konfliktów. Przestrzeganie poniższych reguł może znacząco
ułatwić łączenie kodu:
$ svn co -r 25 file://repo/path/trunk merge_wc
$ svn merge -r 13:head file://repo/path/branches/mybranch merge_wc
… # resolve conflicts
$ indent -gnu src/*.[ch]
$ svn up
… # resolve conflicts
$ svn commit -m 'Merged branch'
Tłumacząc to na polski:
Wyprowadź kopię roboczą sprzed reformatowania.
Dołącz wszystkie zmiany z zadanej gałęzi. Rozwiąż konflikty.
Przeformatuj kod.
Zaktualizuj kopię do głównej wersji. Rozwiąż konflikty.
Wprowadź nową wersję z połączonej kopii roboczej.
Ignorowanie różnic w białych znakach
Przeglądając różnice między wersjami, można wyregulować wynik
polecenia svn diff tak, by różnice w białych znakach
zostały ukryte. Opcja przekazuje wszystkie swoje
argumenty do polecenia GNU diff. Niektóre, warte uwagi, argumenty:
OpcjaOpisIgnoruj zmiany tylko w białych znakach.Ignoruj dodane/usunięte puste linie.Ignoruj zmiany w wielkości liter.Rozszerz spacje, by zachować wyrównanie.Wyświetlaj tabulację zamiast spacji na początku każdej
linii, zaczynającej się na pozycji tabulacji (tab stop).
Emaile wysyłane przy zatwierdzaniu zawsze pokazują zmiany tylko
w białych znakach. Polecenie commit-email.pl używa
komendy svnlook diff do pobrania różnic, a która nie
wspiera opcji .
Zakończenia linii
Różne platformy (Unix, Windows, MacOS) utrzymują różne konwencje
oznaczania końca linii w plikach tekstowych. Proste edytory
mogą nadpisywać zakończenia linii, powodując problemy z różnicowaniem
i łączeniem. Jest to część problemów związanych z reformatowaniem.
Subversion posiada wbudowaną obsługę normalizacji znaków końca linii.
By ją włączyć, trzeba ustawić własność svn:eol-style
na wartość "native". Zajrzyj do podrozdziału Własności w Podręczniku
Subversion by uzyskać więcej informacji.
Gdy zatwierdzasz wersje
Przejrzenie wszystkich zmian i stworzenie sensownego wpisu logu
bardzo popłaca. W zasadzie publikuje się nowy projekt przy zatwierdzeniu
każdej zmiany. Ma to dwa znaczenia:
Gdy zatwierdza się zmiany, można potencjalnie zdestabilizować
główną linię kodu. Wiele projektów zakłada, że główna linia
jest stabilna—powinna zawsze się
parsować/kompilować, przechodzić pozytywnie jednostki testowe,
itp. Jeśli coś pójdzie źle, może to utrudnić pracę wielu ludziom,
dopóki ktoś nie zatwierdzi poprawki.
Nie można łatwo usunąć wersji. (Nie ma czegoś takiego jako
polecenie cvs admin -o.) Jeśli w kopii roboczej
jest element niepożądany w repozytorium, należy się upewnić że
nie jest on załączony w poleceniu zatwierdzenia.
Szczególnie należy zwrócić uwagę na ważne (prywatne) informacje, pliki
wygenerowane automatycznie czy też niepotrzebnie duże pliki.
Jeśli zajdzie konieczność zmiany wpisu logu, istnieje możliwość jego
zmiany. Polecenie svnadmin setlog zrobi to
lokalnie. Można ustawić skrypt http://svn.collab.net/repos/svn/trunk/tools/cgi/tweak-log.cgi,tweak-log.cgi
by zezwolić na zmiany wpisów zdalnie. Jak zawsze, stworzenie zawczasu
przemyślanego i klarownego wpisu pomaga wyrazić swoje myśli i uniknąć
zatwierdzenia błędu czy pomyłki.
Przed każdym zatwierdzeniem powinno się samemu uruchomić polecenie
svn diff i zadać pytania:
czy te zmiany tworzą logiczną całość? Najlepiej gdy każda wersja
to pojedyncza lokalna zmiana. Bardzo łatwo jest zapomnieć,
że już się zaczęło kolejną zmianę.
czy mogę stworzyć dobry wpis logu dla tych zmian?
Stworzenie polityki tworzenia wpisów logu też może być pomocne ---
dokument HACKING z Subversion http://svn.collab.net/repos/svn/trunk/HACKING
stanowi dobrą podstawę. Jeśli zawsze załączasz nazwy plików, funkcji
itp. to łatwo można przeglądać logi za pomocą
search-svnlog.pl http://svn.collab.net/repos/svn/trunk/tools/client-side/search-svnlog.pl.
Można tworzyć wpis logu "w locie". To powszechna praktyka; tworzy się
plik changes zawierający wpis poprawiany
na bieżąco. W czasie zatwierdzania należy użyć polecenia
svn ci -F changes.
Jeśli taki wpis nie powstaje na bieżąco, można utworzyć początkowy
wpis poprzez użycie wyjścia polecenia svn
status (które zawiera spis wsyzstkich zmodyfikowanych
plików/katalogów) i dopisać komentarz dla każdego z nich.
Pliki binarne
Subversion nie umie w żaden sposób połączyć lub przejrzeć
różnic w plikach binarnych, więc dokładność wpisów logu
dla takich plików jest czynnikiem krytycznym.
Ze względu na niemożność użycia polecenia svn diff,
dobrym pomysłem jest tworzenie wpisu dla takich plików na bieżąco,
wraz z pracą nad nimi.
Tłumaczenie: Marcin Dentharg Gil [mgil : bmp net pl]