Dlaczego rozgałęzianie i scalanie jest łatwiejsze w Mercurial niż w Subversion?

92

Obsługa wielu scaleń na gałęziach w Subversion lub CVS jest tylko jedną z tych rzeczy, których trzeba doświadczyć. Niezwykle łatwiej jest śledzić gałęzie i połączenia w Mercurial (i prawdopodobnie każdym innym systemie rozproszonym), ale nie wiem dlaczego. Czy ktoś jeszcze wie?

Moje pytanie wynika z faktu, że z Mercurialem możesz przyjąć praktykę pracy podobną do tej z centralnego repozytorium Subversions / CVS i wszystko będzie działać dobrze. Możesz wykonać wiele scaleń na tej samej gałęzi i nie będziesz potrzebować niekończących się skrawków papieru z numerami zmian i nazwami znaczników.

Wiem, że najnowsza wersja Subversion ma możliwość śledzenia połączeń z gałęziami, więc nie ma takiego samego stopnia kłopotów, ale był to ogromny i poważny rozwój z ich strony i nadal nie robi wszystkiego, co zrobiłby zespół programistów lubię to robić.

Musi istnieć zasadnicza różnica w sposobie, w jaki to wszystko działa.

Nick Pierpoint
źródło

Odpowiedzi:

115

W Subversion (i CVS) repozytorium jest przede wszystkim. W git i mercurial tak naprawdę nie ma takiej samej koncepcji repozytorium; tutaj zmiany są głównym tematem.

+1

Problem związany z CVS / SVN wynika z faktu, że systemy te nie pamiętają rodzicielstwa zmian. W Git i Mercurial zatwierdzenie może mieć nie tylko wiele dzieci, ale także wielu rodziców!

Można to łatwo zaobserwować za pomocą jednego z narzędzi graficznych gitklub hg view. W poniższym przykładzie gałąź # 2 została rozwidlona z # 1 w zatwierdzeniu A i od tego czasu została scalona raz (w M, ​​połączona z zatwierdzeniem B):

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

Zwróć uwagę, że A i B mają dwoje dzieci, podczas gdy M ma dwoje rodziców . Te relacje są rejestrowane w repozytorium. Powiedzmy, że opiekun gałęzi nr 2 chce teraz scalić najnowsze zmiany z gałęzi nr 1, może wydać takie polecenie:

$ git merge branch-1

a narzędzie automatycznie rozpozna, że baza jest B - ponieważ została zapisana w zatwierdzeniu M, przodku końcówki # 2 - i że musi scalić wszystko, co wydarzyło się między B i C. CVS nie rejestruje tych informacji , ani SVN przed wersją 1.5. W tych systemach wykres wyglądałby następująco:

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

gdzie M jest po prostu gigantycznym „zduszonym” zatwierdzeniem wszystkiego, co wydarzyło się między A i B, nałożonym na M. Zauważ, że po wykonaniu czynu nie ma już śladu (z wyjątkiem potencjalnie czytelnych dla człowieka komentarzy) gdzie nie wywodzi się ani z tego, jak wiele zobowiązań zostało razem upadłych - czyniąc historię znacznie bardziej nieprzeniknioną.

Co gorsza, wykonanie drugiego scalenia staje się koszmarem: trzeba dowiedzieć się, co baza seryjnej był w momencie pierwszego scalenia (i jeden ma do wiedzieć , że doszło do seryjnej w pierwszej kolejności!), A następnie obecny że informacje do narzędzia, aby nie próbowało odtworzyć A..B na początku M. Wszystko to jest wystarczająco trudne podczas pracy w ścisłej współpracy, ale jest po prostu niemożliwe w środowisku rozproszonym.

Problem (pokrewny) polega na tym, że nie ma sposobu, aby odpowiedzieć na pytanie: „czy X zawiera B?” gdzie B to potencjalnie ważna poprawka błędu. Dlaczego więc nie zapisać tej informacji w zatwierdzeniu, skoro jest ona znana w czasie scalania!

P.-S. - Nie mam doświadczenia z możliwościami scalania SVN 1.5+, ale przepływ pracy wydaje się być znacznie bardziej skomplikowany niż w systemach rozproszonych. Jeśli tak jest, to prawdopodobnie dlatego, że - jak wspomniano w powyższym komentarzu - nacisk kładziony jest na organizację repozytorium, a nie na same zmiany.

Damien Diederen
źródło
6
SVN 1.5+ rzeczywiście umieściłby właściwość SVN na zatwierdzeniu scalającym M, wymieniając zawarte w nim scalone commity, innymi słowy AB. Więc masz te same informacje.
Simon D
Rodzaj. Technicznie rzecz biorąc, śledzenie scalania SVN jest podobne do tego, co Git nazywa „wybieraniem wiśni”, z dodatkową magią ułatwiającą użytkownikowi; różni się semantycznie od tego, co robią Git, Hg i Bzr podczas łączenia. Wydaje mi się, że w praktyce nie robi to dużej różnicy, o ile nie przejmujesz się DAG ( eagain.net/articles/git-for-computer-scientists ).
Damien Diederen
2
Biada, że ​​nie ma przycisku +100. Dzięki.
Charlie Flowers
Zakładam, że funkcja SVN 1.5, o której mówisz, to korzystanie z svn:mergeinfonieruchomości?
MatrixFrog,
@MatrixFrog: Tak, właśnie to svn:mergeinforobi.
sleske
12

Ponieważ Subversion (przynajmniej wersja 1.4 i niższe) nie śledzi tego, co zostało scalone. W przypadku Subversion scalanie jest zasadniczo takie samo, jak każde zatwierdzenie, podczas gdy przy innej kontroli wersji, takiej jak Git, zapamiętywane są to, co zostało scalone.

htanata
źródło
7

Nie dotknięty żadną z już udzielonych odpowiedzi, Hg oferował lepsze możliwości scalania, ponieważ wykorzystuje więcej informacji podczas scalania zmian ( hginit.com ):

Na przykład, jeśli trochę zmienię funkcję, a następnie przeniosę ją w inne miejsce, Subversion tak naprawdę nie pamięta tych kroków, więc kiedy nadejdzie czas na scalenie, może pomyśleć, że nowa funkcja pojawiła się nieoczekiwanie . Podczas gdy Mercurial zapamięta te rzeczy oddzielnie: funkcja zmieniona, funkcja przesunięta, co oznacza, że ​​jeśli zmienisz również nieco tę funkcję, jest znacznie bardziej prawdopodobne, że Mercurial pomyślnie połączy nasze zmiany.

Oczywiście pamiętanie o tym, co ostatnio zostało scalone (kwestia, do której odnosi się większość udzielonych tutaj odpowiedzi) również jest ogromną wygraną.

Oba ulepszenia są jednak wątpliwe, ponieważ subversion 1.5+ przechowuje dodatkowe informacje o scalaniu w postaci właściwości subversion: te informacje są dostępne, nie ma oczywistego powodu, dla którego scalanie subversion nie mogłoby zaimplementować scalania tak skutecznie, jak Hg lub Git. Nie wiem, czy tak, ale z pewnością wygląda na to, że programiści Subversion są na najlepszej drodze, aby obejść ten problem.

Tomislav Nakic-Alfirevic
źródło
4

Przypuszczam, że może to częściowo wynikać z tego, że Subversion ma pomysł na centralny serwer wraz z bezwzględną linią czasu zmian. Mercurial jest naprawdę rozproszony i nie ma takiego odniesienia do bezwzględnej linii czasu. Pozwala to projektom Mercurial na tworzenie bardziej skomplikowanych hierarchii gałęzi w celu dodawania funkcji i cykli testowania według podprojektów, jednak zespoły muszą teraz znacznie aktywniej kontrolować połączenia, aby pozostać na bieżąco, ponieważ nie mogą po prostu trafić na aktualizację i zrobić z nią .

Zły Andy
źródło
3

W Subversion (i CVS) repozytorium jest przede wszystkim. W git i mercurial tak naprawdę nie ma takiej samej koncepcji repozytorium; tutaj zmiany są głównym tematem.

Nie zastanawiałem się zbytnio nad tym, jak zaimplementujesz, ale moje wrażenie (oparte na gorzkim doświadczeniu i dużej ilości lektur) jest takie, że ta różnica sprawia, że ​​łączenie i rozgałęzianie jest o wiele łatwiejsze w systemach bez repozytoriów.

Stephen Darlington
źródło
1

Mam tylko doświadczenie z Subversion, ale mogę powiedzieć, że ekran scalania w TortoiseSVN jest okropnie skomplikowany. Na szczęście zawierają przycisk biegu na sucho, dzięki czemu możesz sprawdzić, czy robisz to dobrze. Komplikacja polega na konfiguracji tego, co chcesz scalić z miejscem. Po skonfigurowaniu scalania zazwyczaj scalanie przebiega dobrze. Następnie musisz rozwiązać wszystkie konflikty, a następnie przekazać scaloną kopię roboczą do repozytorium.

Jeśli Mercurial może ułatwić konfigurację scalania, to mogę powiedzieć, że scalenie byłoby w 100% łatwiejsze niż Subversion.

Czerwone Wilki
źródło