Łączenie: Hg / Git kontra SVN

144

Często czytam, że Hg (i Git i ...) są lepsze w łączeniu niż SVN, ale nigdy nie widziałem praktycznych przykładów, gdzie Hg / Git może scalić coś, gdzie SVN zawodzi (lub gdzie SVN wymaga ręcznej interwencji). Czy mógłbyś opublikować kilka list krok po kroku operacji rozgałęzień / modyfikacji / zatwierdzeń /...-, które pokazują, gdzie SVN zawiedzie, podczas gdy Hg / Git szczęśliwie rusza dalej? Praktyczne, niezbyt wyjątkowe przypadki proszę ...

Trochę tła: mamy kilkudziesięciu programistów pracujących nad projektami wykorzystującymi SVN, z każdym projektem (lub grupą podobnych projektów) w swoim własnym repozytorium. Wiemy, jak zastosować gałęzie wydania i funkcji, więc nie napotykamy zbyt często problemów (tj. Byliśmy tam, ale nauczyliśmy się przezwyciężyć problemy Joela dotyczące „jednego programisty powodującego traumę dla całego zespołu” lub „potrzeba sześciu programistów na dwa tygodnie w celu ponownej integracji oddziału”). Mamy gałęzie wydania, które są bardzo stabilne i używane tylko do naprawiania błędów. Mamy trunki, które powinny być wystarczająco stabilne, aby móc utworzyć wydanie w ciągu tygodnia. Mamy też gałęzie funkcji, nad którymi mogą pracować pojedynczy programiści lub grupy programistów. Tak, są usuwane po ponownej integracji, aby nie zaśmiecały repozytorium. ;)

Więc wciąż próbuję znaleźć zalety Hg / Git nad SVN. Chciałbym zdobyć praktyczne doświadczenie, ale nie ma jeszcze żadnych większych projektów, które moglibyśmy przenieść na Hg / Git, więc utknąłem z graniem z małymi sztucznymi projektami, które zawierają tylko kilka zmyślonych plików. I szukam kilku przypadków, w których można poczuć imponującą moc Hg / Git, ponieważ do tej pory często o nich czytałem, ale nie udało mi się ich znaleźć.

stmax
źródło
2
Myślę, że powinieneś zwrócić uwagę na dokładne duplikaty: stackoverflow.com/questions/43995/… stackoverflow.com/questions/459891/…
P Shved
11
Przeczytałem już pierwszą, druga była nowa. Ale mają już 1-2 lata i wydają się być głównie związane z problemami sprzed svn-1.5 (gdzie svn nie miał jeszcze śledzenia scalania).
stmax
2
Tylko komentarz, że możesz również wrzucić Bazaar z git / hg jako kolejny DVCS, który poprawnie rozwiąże poniższe problemy. A skoro wspomniałeś o szukaniu korzyści: jedną prostą logistyczną zaletą git / hg / bzr jest to, że gałęzie nie są globalne, jak w przypadku svn. Nie musisz widzieć 67 oddziałów, gdy zgłasza się do Ciebie tylko para. Każdy wykonuje swoją pracę w „prywatnych” oddziałach, a następnie korzysta z doskonałej możliwości scalania, aby ponownie połączyć się bez przejmowania się, czy scalenie będzie działać w 99% przypadków.
wadesworld
5
@wade: czy postrzegasz „prywatne” oddziały jako zaletę w środowisku korporacyjnym? martwię się o kopie zapasowe. często mam gałęzie, które żyją 1-2 miesiące przed ponowną integracją ..
stmax
9
@stmax: ważny problem. Jednak to, co można znaleźć w wielu środowiskach korporacyjnych z subversion, to fakt, że ludzie wstrzymują się z zameldowaniem, dopóki ich kod nie będzie doskonały, a ty masz tam taką samą widoczność.
wadesworld

Odpowiedzi:

91

Sam nie używam Subversion, ale z informacji o wydaniu Subversion 1.5: Śledzenie scalania (podstawowe) wygląda na to, że istnieją następujące różnice w stosunku do tego, jak działa śledzenie scalania w systemach kontroli wersji z pełnym DAG , takich jak Git lub Mercurial.

  • Łączenie magistrali do gałęzi różni się od łączenia gałęzi do gałęzi: z jakiegoś powodu łączenie magistrali do gałęzi wymaga --reintegrateopcji svn merge.

    W rozproszonych systemach kontroli wersji, takich jak Git czy Mercurial, nie ma technicznej różnicy między główną a gałęzią: wszystkie gałęzie są sobie równe ( choć mogą istnieć różnice społeczne ). Scalanie w dowolnym kierunku odbywa się w ten sam sposób.

  • Musisz podać opcję new -g( --use-merge-history) svn logi svn blamewziąć pod uwagę śledzenie scalania.

    W Git i Mercurial śledzenie scalania jest automatycznie uwzględniane podczas wyświetlania historii (dziennika) i winy. W Git możesz poprosić o śledzenie tylko pierwszego rodzica --first-parent(myślę, że podobna opcja istnieje również dla Mercurial), aby „odrzucić” informacje o śledzeniu scalania w git log.

  • Z tego, co rozumiem, svn:mergeinfowłaściwość przechowuje informacje o konfliktach dla poszczególnych ścieżek (Subversion opiera się na zestawie zmian), podczas gdy w Git i Mercurial jest to po prostu zatwierdzanie obiektów, które mogą mieć więcej niż jednego rodzica.

  • Podsekcja „Znane problemy” dotycząca śledzenia scalania w Subversion sugeruje, że powtarzane / cykliczne / refleksyjne scalanie może nie działać poprawnie. Oznacza to, że przy następujących historiach drugie scalanie może nie przynieść właściwego efektu („A” może oznaczać linię główną lub gałąź, a „B” może oznaczać odpowiednio gałąź lub linię główną):

    * --- * --- x --- * --- y --- * --- * --- * --- M2 <- A
             \ \ /
              - * ---- M1 --- * --- * --- / <- B
    

    W przypadku, gdy powyższa grafika ASCII zostanie zerwana: gałąź `` B '' jest tworzona (rozwidlana) z gałęzi `` A '' w wersji `` x '', a później gałąź `` A '' jest scalana w wersji `` y '' do gałęzi `` B '' jako scal 'M1', a na koniec gałąź 'B' jest połączona z gałęzią 'A' jako scalenie 'M2'.

    * --- * --- x --- * ----- M1 - * --- * --- M2 <- A
             \ / / 
              \ - * --- y --- * --- * --- / <- B
    

    W przypadku, gdy powyższa grafika ASCII zostanie zerwana: gałąź „B” jest tworzona (rozwidlana) z gałęzi „A” w wersji „x”, jest scalana do gałęzi „A” w pozycji „y” jako „M1”, a później ponownie połączone w gałąź „A” jako „M2”.

  • Subversion może nie obsługiwać zaawansowanych przypadków scalania krzyżowego .

    * --- b ----- B1 - M1 - * --- M3
         \ \ / /
          \ X /
           \ / \ /
            \ - B2 - M2 - *
    

    Git radzi sobie dobrze z tą sytuacją w praktyce, używając strategii scalania „rekurencyjnego”. Nie jestem pewien co do Mercurialu.

  • W sekcji „Znane problemy” jest ostrzeżenie, że śledzenie scalania może nie działać ze zmianami nazw plików, np. Gdy jedna strona zmienia nazwę pliku (i być może modyfikuje go), a druga strona modyfikuje plik bez zmiany nazwy (pod starą nazwą).

    Zarówno Git, jak i Mercurial radzą sobie dobrze z takim przypadkiem w praktyce: Git wykorzystujący wykrywanie zmian nazwy , Mercurial wykorzystujący śledzenie zmian nazw .

HTH

Jakub Narębski
źródło
jakoś (błąd w parserze Markdown?) część po <pre>...</pre>bloku nie jest wcięta tak, jak powinno ...
Jakub Narębski
1
+1 za wiele szczegółowych przykładów. Nie rozumiem jeszcze, dlaczego przykład w pierwszej ascii-art może powodować problemy. wygląda na standardowy sposób traktowania gałęzi cech: załóżmy, że A to pnia, B to gałąź funkcji. scalasz co tydzień od A do B, a kiedy skończysz z funkcją, scalasz wszystko od B do A, a następnie usuwasz B., który zawsze działał dla mnie. czy źle zrozumiałem schemat?
stmax
1
Zauważ, że nie wiem (nie sprawdziłem), że przykłady podane powyżej naprawdę powodują problemy w Subversion . Myślę, że zmiany nazw i scalanie krzyżowe są prawdziwym problemem w SVN.
Jakub Narębski
2
scalanie reintegracyjne jest specjalną opcją pomagającą w najczęstszym przypadku łączenia - nie ma też technicznej różnicy między gałęziami i pnia w svn. Zwykle nigdy go nie używam i trzymam się standardowej opcji scalania. Mimo to jedynym problemem związanym z scalaniem svn jest to, że traktuje przenoszenie / zmianę nazwy jako usuwanie + dodawanie.
gbjbaanb
--reintegratejest przestarzałe.
naught101
120

Ja również szukałem przypadku, w którym, powiedzmy, Subversion nie łączy gałęzi, a Mercurial (i Git, Bazaar, ...) postępuje właściwie.

Książka SVN opisuje, w jaki sposób pliki o zmienionych nazwach są nieprawidłowo scalane . Dotyczy to Subversion 1.5 , 1.6 , 1.7 i 1.8 ! Próbowałem odtworzyć poniższą sytuację:

cd / tmp
rm - rf svn - repo svn - checkout
svnadmin create svn - repo
svn plik do pobrania : /// tmp / svn - repo svn - checkout
cd svn - do kasy
gałęzie pnia mkdir
echo 'Do widzenia, świecie!' > bagażnik / witam .tekst
svn dodaje gałęzie pnia
svn commit - m 'Początkowy import.' 
svn copy '^ / trunk' '^ / branches / rename' - m 'Create branch.' 
svn przełącznik „^ / trunk” . 
echo 'Witaj świecie!'    > witam .tekst
svn commit - m 'Aktualizacja linii głównej.' 
svn switch '^ / branches / rename' . 
svn rename hello . txt witam . en .tekst
svn commit - m 'Zmień nazwę w gałęzi.' 
svn przełącznik „^ / trunk” . 
svn merge - reintegracja '^ / branches / rename'

Według książki scalanie powinno zakończyć się czysto, ale z błędnymi danymi w pliku o zmienionej nazwie, ponieważ trunkzapomniano o aktualizacji . Zamiast tego pojawia się konflikt drzewa (to jest z Subversion 1.6.17, najnowszą wersją Debiana w momencie pisania):

--- Scalanie różnic między adresami URL repozytoriów w „.”:
Plik hello.pl.txt
   C hello.txt
Podsumowanie konfliktów:
  Konflikty drzew: 1

W ogóle nie powinno być konfliktu - aktualizacja powinna zostać wkomponowana w nową nazwę pliku. Podczas gdy Subversion kończy się niepowodzeniem, Mercurial obsługuje to poprawnie:

rm -rf /tmp/hg-repo
hg init /tmp/hg-repo
cd /tmp/hg-repo
echo 'Goodbye, World!' > hello.txt
hg add hello.txt
hg commit -m 'Initial import.'
echo 'Hello, World!' > hello.txt
hg commit -m 'Update.'
hg update 0
hg rename hello.txt hello.en.txt
hg commit -m 'Rename.'
hg merge

Przed scaleniem repozytorium wygląda następująco (z hg glog ):

@ zestaw zmian: 2: 6502899164cc
| tag: wskazówka
| rodzic: 0: d08bcebadd9e
| użytkownik: Martin Geisler
| data: Czw 01 Kwi 12:29:19 2010 +0200
| podsumowanie: Zmień nazwę.
|
| o zestaw zmian: 1: 9d06fa155634
| / użytkownik: Martin Geisler 
| data: Czw 01 Kwi 12:29:18 2010 +0200
| podsumowanie: aktualizacja.
|
o zestaw zmian: 0: d08bcebadd9e
   użytkownik: Martin Geisler 
   data: Czw 01 Kwi 12:29:18 2010 +0200
   podsumowanie: pierwszy import.

Wynik scalenia to:

scalanie hello.en.txt i hello.txt do hello.en.txt
0 plików zaktualizowanych, 1 połączonych, 0 usuniętych, 0 nierozwiązanych
(łączenie gałęzi, nie zapomnij o zatwierdzeniu)

Innymi słowy: Mercurial wziął zmianę z wersji 1 i połączył ją z nową nazwą pliku z wersji 2 ( hello.en.txt). Obsługa tego przypadku jest oczywiście niezbędna do obsługi refaktoryzacji, a refaktoryzacja jest dokładnie tym, co chcesz zrobić w gałęzi.

Martin Geisler
źródło
+1 dla szczegółowego przykładu można dotknąć klawiatury i na własne oczy zobaczyć, co się stanie. Jako Mercurial noob, zastanawiam się, czy wersja tego przykładu hg jest w oczywisty sposób następująca, linia po linii?
DarenW
4
@DarenW: Dodałem odpowiednie polecenia Mercurial, mam nadzieję, że wszystko to wyjaśni!
Martin Geisler
17

Nie wspominając o zwykłych zaletach (zatwierdzenia offline, proces publikacji , ...) oto przykład „scalania”, który mi się podoba:

Główny scenariusz, który ciągle widzę, to gałąź, na której ... faktycznie powstają dwa niepowiązane zadania
(zaczęło się od jednej funkcji, ale doprowadziło do rozwoju drugiej funkcji.
Lub zaczęło się od poprawki, ale prowadziło do rozwój innej cechy).

Jak połączyć tylko jedną z dwóch funkcji w głównej gałęzi?
Albo jak wyodrębnić te dwie funkcje w ich własnych gałęziach?

Możesz spróbować wygenerować jakieś poprawki, problem polega na tym, że nie jesteś już pewien funkcjonalnych zależności, które mogły istnieć między:

  • zatwierdzenia (lub wersja dla SVN) użyte w twoich łatkach
  • inne zatwierdzenia nie są częścią łatki

Git (i przypuszczam, że Mercurial też) proponuje opcję rebase --onto do rebase (resetowania katalogu głównego gałęzi) części gałęzi:

Z postu Jefromiego

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

możesz rozwikłać tę sytuację, w której masz łatki dla v2, a także nową funkcję wss na:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

, umożliwiając:

  • przetestuj każdą gałąź osobno, aby sprawdzić, czy wszystko kompiluje się / działa zgodnie z przeznaczeniem
  • połącz tylko to, co chcesz, aby główne.

Inną funkcją, która mi się podoba (która wpływa na scalenie), jest możliwość zgniatania zatwierdzeń (w gałęzi, która nie została jeszcze przeniesiona do innego repozytorium) w celu przedstawienia:

  • czystsza historia
  • zatwierdzenia, które są bardziej spójne (zamiast zatwierdzania1 dla funkcji1, zatwierdzania2 dla funkcji2, zatwierdzania3 ponownie dla funkcji1 ...)

Zapewnia to dużo łatwiejsze połączenia i mniej konfliktów.

VonC
źródło
svn nie ma zatwierdzeń offline? rofl? jak ktokolwiek może nawet zdalnie rozważyć jego użycie, jeśli tak jest?
o0 '.
@Lohoris Kiedy pojawił się SVN, nie było powszechnie używanych DVCS typu open source; w tym momencie myślę, że to głównie bezwładność, że ludzie nadal go używają.
Max Nanasy,
@MaxNanasy to bardzo zły rodzaj bezwładności ... jednak wybranie go teraz byłoby po prostu głupie.
o0 '.
@Lohoris Online (dokładniej, scentralizowane) zatwierdzenia nie są tak wielkim problemem w małym zespole, w którym repozytorium może po prostu znajdować się na współdzielonym serwerze lokalnym. DVCS zostały wymyślone głównie dla dużych, rozproszonych geograficznie zespołów (zarówno git, jak i mercurial miały zarządzać kodem jądra Linuksa) i projektów open source (stąd popularność GitHub). Bezwładność można również postrzegać jako ocenę ryzyka i korzyści wynikających ze zmiany narzędzia kluczowego dla przepływu pracy zespołu.
IMSoP
1
@Lohoris Myślę, że źle zrozumiałeś mój punkt widzenia na temat DB, zapory ogniowej itp.: Nie ma sensu, bym mógł zatwierdzić na moim komputerze domowym, jeśli nie mogę faktycznie najpierw uruchomić tego kodu. I mógłby pracować ślepy, ale fakt, że nie mogę popełnić rzeczy gdzieś nie byłoby najważniejsze oddanie mnie.
IMSoP
8

Niedawno przeprowadziliśmy migrację z SVN do GIT i stanęliśmy w obliczu tej samej niepewności. Było wiele anegdotycznych dowodów na to, że GIT był lepszy, ale trudno było znaleźć jakiekolwiek przykłady.

Mogę jednak powiedzieć, że GIT jest DUŻO LEPSZY w łączeniu niż SVN. To oczywiście anegdota, ale jest tabela, której należy przestrzegać.

Oto kilka rzeczy, które znaleźliśmy:

  • SVN wywoływał wiele konfliktów drzew w sytuacjach, w których wydawało się, że nie powinien. Nigdy nie dotarliśmy do sedna tego, ale tak się nie dzieje w GIT.
  • Chociaż lepszy, GIT jest znacznie bardziej skomplikowany. Poświęć trochę czasu na trening.
  • Byliśmy przyzwyczajeni do Tortoise SVN, który nam się podobał. GIT Tortoise nie jest tak dobry i może cię to zniechęcić. Jednak teraz używam wiersza poleceń GIT, który zdecydowanie wolę od Tortoise SVN lub dowolnego z GUI GIT.

Podczas oceny GIT przeprowadziliśmy następujące testy. Pokazują one GIT jako zwycięzcę, jeśli chodzi o łączenie, ale nie aż tak bardzo. W praktyce różnica jest znacznie większa, ale wydaje mi się, że nie udało nam się odtworzyć sytuacji, z którymi SVN radzi sobie źle.

Ocena łączenia GIT i SVN

cedd
źródło
5

Inni omówili bardziej teoretyczne aspekty tego. Może mógłbym podać bardziej praktyczną perspektywę.

Obecnie pracuję dla firmy, która używa SVN w modelu rozwoju „gałęzi funkcji”. To jest:

  • Żadna praca nie może być wykonana na bagażniku
  • Każdy programista może mieć własne gałęzie
  • Oddziały powinny istnieć przez cały czas trwania podjętego zadania
  • Każde zadanie powinno mieć własną gałąź
  • Połączenia z powrotem do linii głównej wymagają autoryzacji (zwykle przez bugzilla)
  • W sytuacjach, gdy potrzebny jest wysoki poziom kontroli, fuzji może dokonać strażnik

Ogólnie to działa. SVN może być użyty do takiego przepływu, ale nie jest doskonały. Istnieją pewne aspekty SVN, które przeszkadzają i kształtują ludzkie zachowanie. To daje pewne negatywne aspekty.

  • Mieliśmy sporo problemów z ludźmi odchodzącymi z punktów niższych niż ^/trunk. Te mioty łączą rekordy informacyjne w całym drzewie i ostatecznie przerywają śledzenie scalania. Zaczynają się pojawiać fałszywe konflikty i panuje zamieszanie.
  • Pobieranie zmian z pnia do gałęzi jest stosunkowo proste. svn mergerobi co chcesz. Scalanie zmian z powrotem wymaga (powiedziano nam) --reintegratepolecenia scalania. Nigdy tak naprawdę nie rozumiałem tego przełącznika, ale oznacza to, że gałęzi nie można ponownie połączyć z linią główną. Oznacza to, że jest to martwa gałąź i musisz utworzyć nową, aby kontynuować pracę. (Patrz uwaga)
  • Cała sprawa wykonywania operacji na serwerze za pośrednictwem adresów URL podczas tworzenia i usuwania oddziałów naprawdę dezorientuje i przeraża ludzi. Więc unikają tego.
  • Przełączanie się między gałęziami jest łatwe do popełnienia błędu, pozostawiając część drzewa patrzącą na gałąź A, a pozostawiając inną część patrząc na gałąź B. Dlatego ludzie wolą wykonywać całą swoją pracę na jednej gałęzi.

Zwykle zdarza się, że inżynier tworzy gałąź pierwszego dnia. Rozpoczyna pracę i zapomina o niej. Jakiś czas później przychodzi szef i pyta, czy może przenieść swoją pracę do bagażnika. Inżynier bał się tego dnia, ponieważ reintegracja oznacza:

  • Łączenie jego długowiecznej gałęzi z powrotem w linię główną i rozwiązywanie wszystkich konfliktów oraz wypuszczanie niepowiązanego kodu, który powinien znajdować się w oddzielnej gałęzi, ale tak nie było.
  • Usuwanie jego oddziału
  • Tworzenie nowego oddziału
  • Przeniesienie kopii roboczej do nowego oddziału

... a ponieważ inżynier robi to tak mało, jak tylko może, nie pamiętają „magicznego zaklęcia”, które należy wykonać na każdym kroku. Zdarzają się niewłaściwe przełączniki i adresy URL i nagle są w bałaganie i idą po „eksperta”.

W końcu wszystko się uspokaja, a ludzie uczą się, jak radzić sobie z niedociągnięciami, ale każdy nowy starter ma te same problemy. Ostateczna rzeczywistość (w przeciwieństwie do tego, co przedstawiłem na początku) to:

  • Na bagażniku nie jest wykonywana żadna praca
  • Każdy deweloper ma jedną główną gałąź
  • Gałęzie trwają do momentu zwolnienia pracy
  • Zgłoszone poprawki błędów mają zwykle własną gałąź
  • Połączenia z powrotem do linii głównej są wykonywane po autoryzacji

...ale...

  • Czasami praca prowadzi do trunkingu, gdy nie powinna, ponieważ znajduje się w tej samej gałęzi co coś innego.
  • Ludzie unikają łączenia (nawet łatwych rzeczy), więc często pracują w swoich własnych małych bąbelkach
  • Zdarzają się duże fuzje, które powodują ograniczoną ilość chaosu.

Na szczęście zespół jest wystarczająco mały, aby sobie z tym poradzić, ale nie da rady. Chodzi o to, że nic z tego nie jest problemem w CVCS, ale co więcej, ponieważ połączenia nie są tak ważne, jak w DVCS, nie są tak sprytne. To „tarcie przy scalaniu” powoduje zachowanie, co oznacza, że ​​model „gałęzi funkcji” zaczyna się rozpadać. Dobre połączenie musi być cechą wszystkich VCS, a nie tylko DVCS.


Zgodnie z tym istnieje teraz --record-onlyprzełącznik, który może być użyty do rozwiązania --reintegrateproblemu, i najwyraźniej v1.8 automatycznie wybiera, kiedy wykonać ponowną integrację i nie powoduje późniejszej martwej gałęzi

Paul S.
źródło
Jak rozumiem, opcja --reintegrate mówi svn, że już rozwiązałeś konfliktowe zmiany podczas scalania do gałęzi funkcji. W efekcie, zamiast traktować go jako łatkę, nadpisuje całe pliki wersją gałęzi, po sprawdzeniu już w historii scalania, że ​​wszystkie wersje linii głównej zostały włączone do gałęzi.
IMSoP
@IMSoP: prawdopodobnie to ma sens. To nie wyjaśnia mi jednak, dlaczego było to konieczne ani dlaczego uniemożliwiło dalsze łączenie się z tą gałęzią. Nie pomogło również to, że opcja była w dużej mierze nieudokumentowana.
Paul S
Używałem go tylko przez TortoiseSVN, gdzie zawsze było to wyraźnie wyjaśnione w interfejsie scalania. Uważam, że SVN 1.8 automatycznie wybiera właściwą strategię i nie potrzebuje oddzielnej opcji, ale nie wiem, czy naprawili normalny algorytm scalania, aby poprawnie radził sobie z gałęzią, która została zresetowana w ten sposób.
IMSoP
3

Przed Subversion 1.5 (jeśli się nie mylę), Subversion miał znaczną wadę, ponieważ nie pamiętał historii scalania.

Spójrzmy na przypadek przedstawiony przez VonC:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - A - x (v2-only)
           \
             x - B - x (wss)

Zwróć uwagę na wersje A i B. Powiedzmy, że scaliłeś zmiany z wersji A w gałęzi „wss” do gałęzi „tylko v2” w wersji B (z dowolnego powodu), ale nadal korzystałeś z obu gałęzi. Jeśli spróbujesz ponownie scalić dwie gałęzie za pomocą merkurialu, scaliłoby to tylko zmiany po wersjach A i B. W przypadku Subversion musiałbyś scalić wszystko, tak jakbyś wcześniej nie dokonał scalenia.

To jest przykład z mojego własnego doświadczenia, w którym łączenie się z B do A zajęło kilka godzin ze względu na ilość kodu: ponowne przejście przez to byłoby naprawdę trudne , co miałoby miejsce w przypadku subversion przed 1.5.

Kolejna, prawdopodobnie bardziej istotna różnica w zachowaniu podczas łączenia z Hginit: reedukacja Subversion :

Wyobraź sobie, że ty i ja pracujemy nad jakimś kodem, a my rozgałęziamy ten kod i każdy z nas przechodzi do oddzielnych obszarów roboczych i osobno wprowadzamy wiele, wiele zmian w tym kodzie, więc trochę się rozeszły.

Kiedy musimy się scalić, Subversion próbuje spojrzeć na obie wersje - mój zmodyfikowany kod i twój zmodyfikowany kod - i próbuje odgadnąć, jak zmiażdżyć je razem w jednym wielkim, przeklętym bałaganie. Zwykle kończy się niepowodzeniem, tworząc strony i strony „konfliktów scalania”, które tak naprawdę nie są konfliktami, a po prostu miejscami, w których Subversion nie zdołało zrozumieć, co zrobiliśmy.

Z drugiej strony, kiedy pracowaliśmy oddzielnie w Mercurial, Mercurial był zajęty utrzymywaniem serii zestawów zmian. Tak więc, gdy chcemy połączyć nasz kod razem, Mercurial ma w rzeczywistości o wiele więcej informacji: wie, co każdy z nas zmienił i może ponownie zastosować te zmiany, zamiast tylko patrzeć na końcowy produkt i próbować zgadnąć, jak go umieścić razem.

Krótko mówiąc, sposób analizowania różnic przez Mercurial jest (był?) Lepszy od metody wywrotowej.

Tomislav Nakic-Alfirevic
źródło
5
przeczytałem hginit. szkoda, nie pokazuje bardziej praktycznych przykładów tego, gdzie hg radzi sobie lepiej niż svn .. w zasadzie mówi ci, żebyś "zaufał joelowi", że hg jest po prostu lepszy. proste przykłady, które pokazał, prawdopodobnie można by również wykonać za pomocą svn ... właściwie dlatego otworzyłem to pytanie.
stmax
1
Opierając się na tym, jak to się mówi, przychodzi na myśl naiwne pytanie: co by było, gdyby algorytm scalania Mercuriala został umieszczony w Subversion? Czy svn byłby wtedy tak dobry jak hg? Nie, ponieważ zaletą hg jest organizacja wyższego poziomu, a nie niskopoziomowa matematyka tekstowa polegająca na łączeniu wierszy z plików. To nowatorski pomysł, który my użytkownicy svn powinniśmy sobie uświadomić.
DarenW
@stmax: Rozumiem, co masz na myśli. Jednak opinia Joela lub kogokolwiek innego nie ma tak naprawdę znaczenia: jedna technologia jest albo lepsza od drugiej (dla zestawu przypadków użycia), albo nie. @DarenW i @stmax: z własnego doświadczenia wynika, że ​​Hg wygrywa z powodu rozproszonego działania (nie jestem cały czas podłączony), wydajności (wiele operacji lokalnych), niezwykle intuicyjnego rozgałęziania wspomaganego przez doskonały algorytm scalania, hg rollback, szablony wyjścia dziennika, hg glog, pojedynczy folder .hg ... Mógłbym po prostu kontynuować i dalej i dalej ... wszystko inne niż może git i bazaar wydaje się być kaftanem bezpieczeństwa.
Tomislav Nakic-Alfirevic
Cytowany komentarz hg dotyczący „zestawów zmian” wydaje mi się raczej niedokładny. SVN doskonale wie, jakie zmiany się łączy (zbiór zmian to w zasadzie różnica między dwoma migawkami i odwrotnie, prawda?) I może zastosować każdą z nich po kolei, jeśli sobie tego życzy; na pewno nie musi niczego „zgadywać”. Jeśli robi „jeden wielki, przeklęty bałagan”, to jest to problem z implementacją, a nie coś fundamentalnego dla projektu. Głównym problemem, który jest trudny do rozwiązania w ramach obecnego projektu architektury, jest przenoszenie / kopiowanie / zmiana nazwy plików.
IMSoP