Z mojego zrozumienia, SVN jest „łatwy do rozgałęzienia. Trudne do scalenia ”. Dlaczego? Czy jest jakaś różnica, w jaki sposób się łączą?
Zobacz moją odpowiedź Przepełnienie stosu, aby zobaczyć bardzo konkretną sytuację, w której Mercurial (i Git) łączą się bez problemów i gdzie Subversion przedstawia ci fałszywy konflikt. Sytuacja polega na prostym refaktoryzacji w oddziale, w którym zmieniasz nazwy niektórych plików.
Jeśli chodzi o odpowiedź tdammerów, istnieje wiele nieporozumień:
Subversion, Mercurial i Git wszystkie migawki projektu w całym repozytorium ścieżek. Nazywanie ich wersjami , wersjami lub zestawami zmian nie ma znaczenia. Wszystkie są logicznie atomowymi migawkami zestawu plików.
Wielkość twoich commits nie ma znaczenia, jeśli chodzi o scalanie. Wszystkie trzy systemy łączą się ze standardowym trójstronnym algorytmem scalania, a dane wejściowe do tego algorytmu są
Nie ma znaczenia, w jaki sposób powstały dwie wersje gałęzi. Możesz użyć 1000 małych zatwierdzeń od wersji przodka, lub możesz użyć 1 zatwierdzenia. Liczy się tylko ostateczna wersja plików. (Tak, to zaskakujące! Tak, wiele przewodników DVCS robi to okropnie źle).
Podnosi także kilka dobrych punktów na temat różnic:
Subversion ma pewne „voodoo”, gdzie można scalić z /trunk
do, powiedzmy, /branches/foo
. Mercurial i Git nie używają tego modelu - gałęzie są modelowane bezpośrednio w historii. Historia staje się zatem ukierunkowanym grafem acyklicznym zamiast liniowym. Jest to o wiele prostszy model niż ten używany przez Subversion i to odcina wiele narożnych obudów.
Możesz łatwo opóźnić scalenie, a nawet pozwolić komuś innemu na jego obsługę. Jeśli hg merge
dajesz mnóstwo konfliktów, możesz poprosić o to swojego współpracownika hg pull
, a on ma dokładnie taki sam stan. Więc może hg merge
i może lepiej radzi sobie z rozwiązywaniem konfliktów niż ty.
Jest to bardzo trudne w przypadku Subversion, gdzie przed aktualizacją musisz dokonać aktualizacji . Nie możesz po prostu zignorować zmian na serwerze i nadal zatwierdzać swój własny anonimowy oddział. Ogólnie rzecz biorąc, siły Subversion Ci poeksperymentować z kopii roboczej brudny kiedy svn update
. Jest to trochę ryzykowne, ponieważ nie zapisałeś żadnych zmian w bezpiecznym miejscu. Git and Mercurial pozwala najpierw zatwierdzić, a następnie zaktualizować i scalić w razie potrzeby.
Prawdziwym powodem, dla którego Git i Mercurial lepiej się łączą niż Subversion, jest kwestia implementacji. Istnieją konflikty nazw, które Subversion po prostu nie może obsłużyć, nawet jeśli jest jasne, jaka jest prawidłowa odpowiedź. Mercurial i Git radzą sobie z nimi łatwo. Ale nie ma powodu, dla którego Subversion również nie poradziłby sobie z nimi - centralizacja z pewnością nie jest powodem.
trunk
w SVN. Za pomocą DVCS możesz dokonywać transakcji bez udostępniania, ale w SVNsvn commit
będziesz mieć bezpośredni wpływ na innych, którzy pracują w tym samym oddziale. Nawet jeśli oboje pracujemy w oddziale w SVN, nie mogę wykonać mojej pracy bez konieczności natychmiastowego połączenia się z twoją pracą. To sprawia, że zatwierdzanie jest nieco przerażające - co jest przerażającą właściwością dla systemu kontroli wersji! :-)Podstawowy problem polega na tym, że systemy te reprezentują wersjonowaną strukturę katalogów.
Podstawową koncepcją Subversion, wokół której obraca się cały system, jest wersja (lub, w svn lingo, „wersja”): migawka pliku w pewnym momencie. Tak długo, jak historia jest idealnie liniowa, wszystko jest w porządku, ale jeśli chcesz połączyć zmiany z dwóch niezależnych linii rozwoju, svn musi porównać bieżące wersje obu, a następnie wykonać trójstronne porównanie między ostatnią udostępnioną wersją i dwie wersje głowy. Linie, które wydają się zmienione w jednej głowicy, ale nie w drugiej, można łatwo rozwiązać; linie odchylające się dokładnie w ten sam sposób w obu głowach są twardsze, ale zwykle wykonalne; linie, które różnią się na różne sposoby, powodują, że svn mówi: „Nie mogę tego rozgryźć, człowieku, proszę, rozwiąż to dla mnie”.
Natomiast zestawy zmian ścieżek git i mercurial zamiast wersji. Całe repozytorium jest drzewem zestawów zmian, każdy w zależności od elementu nadrzędnego, gdzie zestaw nadrzędny może mieć dowolną liczbę elementów podrzędnych, a katalog główny drzewa reprezentuje pusty katalog. Innymi słowy, git / hg mówi „najpierw nie miałem nic, potem ta łatka została zastosowana, potem ta łatka itp.”. Kiedy potrzebujesz połączyć dwie linie rozwoju, git / hg nie tylko wie, jak obecnie wygląda każda głowa i jak wyglądała ostatnia wspólna wersja, ale także wie, jak przebiegło przejście, umożliwiając znacznie inteligentniejsze łączenie.
Kolejną rzeczą, która ułatwia łączenie w DVCS, jest pośrednia konsekwencja rozdzielenia koncepcji zatwierdzenia i wypchnięciaoraz zezwalanie na wszelkiego rodzaju połączenia krzyżowe między dowolnymi dwoma klonami tego samego repozytorium w dowolnym momencie. W przypadku svn ludzie mają tendencję do dokonywania dużych zestawów zmian z często niezwiązanymi ze sobą zmianami, ponieważ zatwierdzenie jest także aktualizacją centralnego repozytorium, która wpływa na wszystkich innych członków zespołu; jeśli popełnisz zepsutą wersję, wszyscy będą na ciebie źli. Ponieważ większość konfiguracji wymaga sieciowego serwera svn, zatwierdzanie wiąże się również z pompowaniem danych przez sieć, co oznacza, że zatwierdzenie wprowadza znaczne opóźnienie w przepływie pracy (szczególnie, gdy twoja kopia robocza jest nieaktualna i musisz najpierw pobrać). W przypadku git i mercurial zatwierdzanie odbywa się lokalnie, a ponieważ oba są bardzo wydajne w obsłudze lokalnych systemów plików, zwykle kończy się natychmiast. W rezultacie ludzie (gdy się do tego przyzwyczają) dokonują niewielkich zmian przyrostowych, a następnie, gdy to działa, naciskać kilkanaście zatwierdzeń za jednym razem. Następnie, gdy nadejdzie czas scalania, SCM ma znacznie bardziej szczegółowe informacje i może lepiej i automatycznie rozwiązywać konflikty.
A potem są ładne szczegóły, które jeszcze bardziej ułatwiają:
źródło
hg mv
lubhg addremove --similarity...
), podczas gdy Git używa heurystyki, ale obie obsługują zmiany nazw . Mogę uzyskać konflikt drzewa nawet z różnicą 1 łańcucha w scalonych plikach! Niestety, musisz ponownie nauczyć się niektórych aspektów Subversion.rename a b
, jakcopy a b; remove a
i zarówno to zrobić w jeden popełnić atomowej. Różnica w zachowaniu podczas scalania wynika z odmiennej obsługi przypadków narożnych oraz z Subversion, która pozwala na więcej połączeń niż Mercurial i Git. Wreszcie, Git wykrywa zmiany nazw podczas scalania i rejestrowania - myślimy o dodaniu tego również w Mercurial.