Możliwa duplikat:
Jestem maniakiem Subversion, dlaczego powinienem brać pod uwagę Mercurial, Git lub inny DVCS?
Co jakiś czas słyszysz, jak ktoś mówi, że rozproszona kontrola wersji (Git, HG) jest z natury lepsza niż scentralizowana kontrola wersji (jak SVN), ponieważ scalanie jest trudne i bolesne w SVN. Chodzi o to, że nigdy nie miałem żadnych problemów z połączeniem się z SVN, a ponieważ kiedykolwiek słyszysz to twierdzenie wysuwane przez zwolenników DVCS, a nie przez rzeczywistych użytkowników SVN, przypomina mi to o tych ohydnych reklamach w telewizji, gdzie spróbuj sprzedać ci coś, czego nie potrzebujesz, przez to, że trzmieli aktorzy udają, że to, co już masz i działa dobrze, jest niezwykle trudne w użyciu.
Niezmiennie podnoszonym przypadkiem użycia jest ponowne połączenie oddziału, co ponownie przypomina mi te reklamy produktów strawman; jeśli wiesz, co robisz, nie powinieneś (i nigdy nie musisz) ponownie łączyć gałęzi. (Oczywiście trudno to zrobić, gdy robisz coś zasadniczo złego i głupiego!)
Pomijając absurdalny przypadek użycia strawmana, co takiego jest w łączeniu SVN, które jest z natury trudniejsze niż łączenie w systemie DVCS?
Odpowiedzi:
To dlatego, że svn nie miał odpowiednich struktur danych, aby dokładnie określić najnowszego wspólnego przodka dwóch gałęzi. Nie jest to wielka sprawa dla gałęzi, która jest scalana tylko raz, ale może powodować wiele błędnych konfliktów scalania w sytuacjach, w których kilka gałęzi jest łączonych wiele razy.
Nie śledzę svn bardzo uważnie, ale rozumiem, że te szczególne problemy techniczne zostały naprawione w ostatnich wersjach. Jednak nie zostało to ustalone wystarczająco wcześnie, aby rozwiać mit, a ludzie, którzy próbowali DVCS do fuzji, trzymali się go z innych powodów.
źródło
I na tym polega źródło twojego zamieszania i cały problem w ogóle.
Mówisz, że łączenie oddziałów jest „zasadniczo złe i głupie”. To jest właśnie problem: myślisz o gałęziach jako o rzeczach, których nie należy łączyć. Czemu? Ponieważ jesteś użytkownikiem SVN, który wie, że łączenie oddziałów jest trudne . Dlatego nigdy tego nie robisz i zachęcasz innych, aby tego nie robili. Zostałeś przeszkolony, aby uniknąć łączenia; opracowałeś techniki, których używasz, aby uniknąć scalania.
Jestem użytkownikiem Mercurial. Nawet przy moich projektach, w których jestem jedynym programistą, cały czas łączę oddziały . Mam gałąź wydania, w której poprawiam. Cóż, łączę to z powrotem z linią główną, aby poprawka tam trafiła.
Gdybym używał SVN, przyjąłbym zupełnie inną strukturę bazy kodu. Czemu? Ponieważ SVN utrudnia scalanie, dlatego opracowujesz idiomy i techniki, aby uniknąć wykonywania złożonych scaleń.
DVCS ułatwiają łączenie złożonych, ponieważ są stanem domyślnym . Wszystko jest mniej więcej gałąź w DVCS. Tak więc cała ich struktura jest zbudowana od podstaw, aby ułatwić łączenie. Pozwala to opracować przepływ pracy, który używa scalania na co dzień, zamiast przepływu pracy SVN, w którym scalanie nigdy nie jest używane.
Prosty fakt jest taki: powinieneś podejść do DVCS w inny sposób niż SVN. Powinieneś używać odpowiednich idiomów dla tych bardzo różnych rodzajów systemów kontroli wersji. W SVN przyjmujesz idiomy, które nie wymagają scalania, ponieważ scalenia są trudne. W DVCS przyjmujesz idiomy, które często używają scalania, ponieważ to nic wielkiego.
Właściwe narzędzie do właściwej pracy.
Chodzi o to, że przepływ pracy skoncentrowany na scalaniu jest o wiele ładniejszy i łatwiejszy w użyciu niż przepływ pracy w stylu SVN, w którym nie scalasz rzeczy. Łatwiej jest zobaczyć, kiedy coś z gałęzi wydania zostało przeniesione do gałęzi deweloperów. Łatwiej jest zobaczyć różne wzajemne oddziaływanie między gałęziami. Łatwo jest tworzyć gałęzie testowe dla rzeczy, a następnie przycinać je, jeśli test nie działa. I tak dalej.
Naprawdę, Joel wyjaśnia to o wiele lepiej niż potrafię . Powinieneś dobrze o tym przeczytać.
źródło
Nie ma nic trudnego w połączeniu SVN ... już ... jeśli postępujesz zgodnie z właściwą filozofią
To, co widzę w większości innych odpowiedzi, wydaje się pochodzić od ludzi, którzy od dawna nie używali SVN. Jak ktoś słusznie wspomina: „nie było wystarczająco wcześnie ustalone, aby rozwiać mit”.
Z mojego obecnego doświadczenia w używaniu SVN 1.6 do 1.8 w odziedziczonym niedawno projekcie, SVN przeszedł długą drogę w kierunku ułatwienia łączenia. Nie jest on jednak niezawodny i myślę, że niełatwo cierpi użytkownikom, którzy odbiegają od zamierzonego zastosowania.
Chociaż znałem SVN całkiem dobrze, a tymczasem próbowałem Mercurial do osobistych projektów, nigdy przedtem nie przeprowadzałem dużo rozgałęzień w SVN. Było sporo prób i błędów, a na początku miałem wiele nieoczekiwanych konfliktów scalania.
Ostatecznie jednak zdałem sobie sprawę, że za każdym razem, gdy dostaję jeden (lub jakiś inny problem), dzieje się tak, ponieważ nie robiłem rzeczy właściwie (inaczej „sposób SVN” - prawdopodobnie właściwy sposób kontroli wersji). Uważam, że na tym polega trudność: nie możesz robić wszystkiego, co chcesz w niezorganizowany sposób, i oczekujesz, że SVN będzie działał idealnie, szczególnie w przypadku fuzji. Połączenia wymagają rygorystycznej dyscypliny od użytkownika (użytkowników), zanim pokażą swoją prawdziwą moc.
Oto rzeczy, które zauważyłem, to mocne rekomendacje, jeśli nie wymagania, dotyczące czystego wykorzystania połączeń:
Jeśli nie zastosujesz się do powyższego, prawdopodobieństwo wystąpienia konfliktów jest bardzo prawdopodobne. Zawsze można je rozwiązać, ale spędzanie czasu nie jest strasznie przyjemne.
Aha, jeszcze jedna rzecz o scalaniu, gdzie, ze wszystkiego, co przeczytałem i wypróbowałem, SVN naprawdę jest do kitu: usunięte / przeniesione / przemianowane pliki / foldery. Najwyraźniej SVN nadal nie może poradzić sobie ze zmianą nazwy, usunięciem lub przeniesieniem pliku w jednej gałęzi, a jego oryginalną wersją zmodyfikowaną w innej gałęzi ... a następnie scaleniem ich ze sobą. Po prostu nie będzie wiedział, gdzie plik poszedł w jedną stronę, i „zapomni” zmiany w drugą stronę. Jedna zmiana jest oczywiście nierozwiązywalna (albo usuwasz, albo zmieniasz plik, nie możesz zrobić obu), ale zastosowanie zmian do przeniesionych / zmienionych nazw plików powinno działać i nie działa. Mam nadzieję, że zostanie to wkrótce naprawione.
Podsumowując, czy łączenie SVN jest łatwe? Nie sądzę. Na pewno nie w beztroski sposób. Czy to źle ? Nie wydaje mi się Pluje z powrotem tylko w twarz, gdy używasz go w niewłaściwy sposób i nie myślisz wystarczająco dużo o tym, co robisz.
Na tej podstawie rozumiem, dlaczego ludzie mogą preferować Mercurial (na przykład), ponieważ z mojego doświadczenia jest trochę łagodniejszy w tych sprawach i miał wszystko zautomatyzowane od samego początku (przynajmniej od wczesnych wersji, z którymi zacząłem). SVN jednak trochę nadrobił zaległości, więc nie warto już tak walić.
źródło
Wewnętrzne modele danych są zasadniczo różne.
Zasadniczo, w SVN, patrząc na historię oddziału, widać tylko to, co się wydarzyło w tym oddziale. Kiedy więc połączysz z gałęzi
B
do gałęziA
, historia gałęziA
będzie zawierała jedno duże zatwierdzenie zawierające wszystkie zmiany wprowadzone wyraźnieB
od czasu jej rozgałęzienia.W pierwszych wersjach SVN, jeśli trzeba było ponownie połączyć gałąź
B
z gałęziąA
, trzeba było ręcznie określić, który zakres wersji gałęziB
chcesz scalić, aby uniknąć podwójnego scalenia tych samych wersji. Sprytny programista użyłby oczywiście komunikatu zatwierdzenia, takiego jak „Scalony w B: 1234”.SVN 1.5 „naprawił” to. Nie zmieniło to jednak zasadniczego zastosowania fuzji. Po prostu dodał kilka dodatkowych metadanych do gałęzi
A
, informując SVN, że wersja 1234 została scalona, umożliwiając SVN automatyczne wybranie prawidłowego zakresu wersji.Ale to rozwiązanie jest w zasadzie obejściem dla modelu danych, który zasadniczo nie obsługuje śledzenia tego, co zostało scalone.
Scalenie dwóch gałęzi jest stosunkowo prostym przykładem. Ale obrazowanie tego bardziej złożonego scenariusza
A
ztrunk
i dokonaj kilku zatwierdzeń tutajB
zA
i dokonaj kilku zatwierdzeń tutajtrunk
iA
B
wtrunk
A
wB
A
wtrunk
B
wtrunk
(to nie powinno nic zrobić)Prawidłowa obsługa tego modelu przy użyciu modelu metadanych staje się niezwykle skomplikowana (nie wiem, czy SVN rzeczywiście poprawnie obsługuje ten scenariusz i nie mam ochoty go testować).
Obsługa tego scenariusza w git jest niezwykle prosta.
W git, za każdym razem, gdy zatwierdzasz, wewnętrzny obiekt reprezentujący to zatwierdzenie zawiera odniesienie do poprzedniej nagłówka. Podczas scalania w gałęzi zatwierdzenie zawiera odniesienia do poprzedniego nagłówka wszystkich łączonych gałęzi (możesz połączyć więcej niż jedną gałąź jednocześnie w git)
Dlatego, gdy badasz historię pojedynczego zatwierdzenia w git, możesz zobaczyć całą historię, możesz zobaczyć, kiedy była rozgałęziona, kiedy została połączona, i możesz zobaczyć historię obu gałęzi między rozgałęzieniem a scaleniem.
Zatem podczas łączenia w oddziale, który został częściowo scalony, niezwykle proste jest ustalenie, co zostało już połączone, a co nie.
Nie mam doświadczenia z Mercurialem, ale podejrzewam, że jego wewnętrzne działanie jest podobne do git.
Zasadniczo więc dla SVN celem projektu było sprawienie, aby rozgałęzianie było tanie. Ale w git, celem projektu było, aby scalanie było tanie.
Wreszcie, kiedy ostatnio użyłem SVN, nie był w stanie obsłużyć scalania, w którym nazwa pliku została zmieniona w jednej gałęzi, a zmodyfikowana w innej.
źródło
Zrobiłem sporo scalania SVN - w tym mając długo działające gałęzie rozwoju i wydania. Ogólnie przeżyłem. Łączenie jest zawsze trudne, ale z DCVS minusem nie jest strasznie źle - wszystko jest lokalne, więc po prostu zaktualizuj znaną dobrą wersję i kontynuuj. Podczas gdy z SVN dużo się stało po stronie serwera, więc odzyskiwanie było brzydkie - zwykle wymagało wymazania lokalnej kopii, a następnie sprawdzenia nowej czystej gałęzi, aby spróbować ponownie. Nie było źle w moim przypadku - pomaga gigabitowe połączenie ze skrzynką SVN. Ale mieliśmy kontrahentów, którzy mieli z tym wiele problemów, ponieważ mieli wolne połączenia, więc wszystko trwało wiecznie, w tym fuzje.
źródło
Oto jedna z bardzo fajnych rzeczy związanych z git. Nie jest dziedziczony po DVCS, jest po prostu czymś, co wyróżnia git. Możesz scalić określone wersje z dowolnego oddziału do innego oddziału. Po prostu bierze różnicę i stosuje ją do drugiej gałęzi, ale śledzi i jest znacznie bardziej automatyczny.
Tak więc, jeśli masz gałąź 2.0 i gałąź 3.0 i odkryjesz błąd w wersji 2.0, możesz go naprawić w wersji 2.0 i wziąć zestaw wersji, które go rozwiązują, i scalić tylko te wersje w gałęzi 3.0. Nie sądzę, aby SVN miał na to inny sposób niż ręczne pobranie różnic dla każdej wersji i zastosowanie ich
Oczywiście wydaje się, że algorytm automatycznego scalania działa znacznie płynniej, a git został zbudowany od podstaw na modelu „stwórz gałąź dla wszystkich rzeczy”, więc rozgałęzianie jest po prostu naprawdę płynne i łatwe. Rozgałęzienie często wydaje się naturalne, jak lekkie są gałęzie
źródło