Jak i / lub dlaczego łączenie się w Git jest lepsze niż w SVN?

400

Słyszałem w kilku miejscach, że jednym z głównych powodów, dla których świecą rozproszone systemy kontroli wersji, jest znacznie lepsze scalanie niż w tradycyjnych narzędziach, takich jak SVN. Czy jest to faktycznie spowodowane nieodłącznymi różnicami w działaniu tych dwóch systemów, czy też konkretne implementacje DVCS, takie jak Git / Mercurial, mają po prostu wyraźniejsze algorytmy scalania niż SVN?

Mr. Boy
źródło
Nadal nie otrzymałem pełnej odpowiedzi po przeczytaniu wspaniałych odpowiedzi tutaj. Przesłane - stackoverflow.com/questions/6172037/…
ripper234
to zależy od twojego modelu. w prostszych przypadkach svn jest często lepszy, ponieważ nie wywołuje przypadkowo połączeń 2-kierunkowych Połączenia 3-drogowe, podobnie jak git, można wykonać, jeśli wypchniesz / scalisz / pociągniesz / wypychasz jedną gałąź rozwoju. patrz: svnvsgit.com
Erik Aronesty

Odpowiedzi:

556

Twierdzenie, dlaczego scalanie jest lepsze w DVCS niż w Subversion, było w dużej mierze oparte na tym, jak rozgałęzianie i scalanie działało w Subversion jakiś czas temu. Subversion w wersji wcześniejszej niż 1.5.0 nie przechowywało żadnych informacji o tym, kiedy gałęzie zostały scalone, dlatego kiedy chciałeś scalić, musisz określić, który zakres wersji musiał zostać scalony.

Dlaczego więc połączenia Subversion są do bani ?

Zastanów się nad tym przykładem:

      1   2   4     6     8
trunk o-->o-->o---->o---->o
       \
        \   3     5     7
b1       +->o---->o---->o

Gdy chcemy scalić zmiany b1 z bagażnikiem, wydamy następujące polecenie, stojąc na folderze, który został wyewidencjonowany:

svn merge -r 2:7 {link to branch b1}

… Który spróbuje scalić zmiany z b1lokalnego katalogu roboczego. Następnie zatwierdzasz zmiany po rozwiązaniu wszelkich konfliktów i przetestowaniu wyniku. Po zatwierdzeniu drzewo wersji będzie wyglądać następująco:

      1   2   4     6     8   9
trunk o-->o-->o---->o---->o-->o      "the merge commit is at r9"
       \
        \   3     5     7
b1       +->o---->o---->o

Jednak ten sposób określania zakresów wersji szybko wymyka się spod kontroli, gdy drzewo wersji rośnie, ponieważ subversion nie ma żadnych metadanych dotyczących tego, kiedy i jakie wersje zostały scalone. Zastanów się, co stanie się później:

           12        14
trunk  …-->o-------->o
                                     "Okay, so when did we merge last time?"
              13        15
b1     …----->o-------->o

Jest to w dużej mierze problem związany z projektem repozytorium, który ma Subversion, aby utworzyć gałąź, musisz utworzyć nowy katalog wirtualny w repozytorium, który będzie zawierał kopię pnia, ale nie przechowuje żadnych informacji dotyczących tego, kiedy i co wszystko z powrotem się połączyło. Czasami doprowadzi to do nieprzyjemnych konfliktów scalania. Jeszcze gorsze jest to, że Subversion domyślnie używał łączenia dwukierunkowego, co ma pewne paraliżujące ograniczenia w automatycznym łączeniu, gdy dwie głowy oddziałów nie są porównywane z ich wspólnym przodkiem.

Aby złagodzić to Subversion przechowuje teraz metadane do rozgałęzienia i scalenia. To rozwiązałoby wszystkie problemy, prawda?

A tak przy okazji, Subversion wciąż jest do bani…

W scentralizowanym systemie, takim jak subversion, wirtualne katalogi są do kitu. Dlaczego? Ponieważ każdy ma dostęp do ich przeglądania… nawet te eksperymentalne. Rozgałęzianie jest dobre, jeśli chcesz eksperymentować, ale nie chcesz widzieć eksperymentów wszystkich i ich ciotek . To poważny hałas poznawczy. Im więcej gałęzi dodasz, tym więcej badziewiasz zobaczysz.

Im więcej oddziałów publicznych znajduje się w repozytorium, tym trudniej będzie śledzić wszystkie różne oddziały. Pytanie, które zadajesz, brzmi: czy gałąź jest wciąż w fazie rozwoju, czy naprawdę jest martwa, co trudno powiedzieć w scentralizowanym systemie kontroli wersji.

Z tego, co widziałem, przez większość czasu organizacja i tak domyślnie korzysta z jednego dużego oddziału. Szkoda, bo to z kolei trudno będzie śledzić testowanie i wydawanie wersji, a wszystko, co dobre, pochodzi z rozgałęziania.

Dlaczego więc DVCS, takie jak Git, Mercurial i Bazaar, są lepsze od Subversion przy rozgałęzianiu i scalaniu?

Istnieje bardzo prosty powód: rozgałęzienie to koncepcja pierwszej klasy . Z założenia nie ma wirtualnych katalogów , a rozgałęzienia są twardymi obiektami w DVCS, które muszą być takie, aby działać po prostu z synchronizacją repozytoriów (tj. Push i pull ).

Pierwszą rzeczą, którą robisz podczas pracy z DVCS, jest klonowanie repozytoriów (git clone, hg clonei bzr branch). Klonowanie jest koncepcyjnie tym samym, co tworzenie gałęzi kontroli wersji. Niektórzy nazywają to rozwidleniem lub rozgałęzieniem (chociaż ten drugi często jest również używany w odniesieniu do kolokacji rozgałęzień), ale to po prostu to samo. Każdy użytkownik prowadzi własne repozytorium, co oznacza, że ​​masz rozgałęzienie dla poszczególnych użytkowników .

Struktura wersji nie jest drzewem , lecz grafem . Mówiąc dokładniej, ukierunkowany wykres acykliczny (DAG, co oznacza wykres, który nie ma żadnych cykli). Naprawdę nie musisz zagłębiać się w specyfikację DAG, inaczej niż każde zatwierdzenie ma jedno lub więcej odwołań nadrzędnych (na podstawie których zatwierdzenie było oparte). Dlatego poniższe wykresy pokażą strzałki między wersjami w odwrotnej kolejności z tego powodu.

Byłby to bardzo prosty przykład łączenia; Wyobraź sobie centralne repozytorium o nazwie origini użytkownika, Alice, klonującego repozytorium na jej maszynę.

         a…   b…   c…
origin   o<---o<---o
                   ^master
         |
         | clone
         v

         a…   b…   c…
alice    o<---o<---o
                   ^master
                   ^origin/master

Podczas klonowania każda kopia jest kopiowana do Alicji dokładnie tak, jak była (co jest potwierdzane przez jednoznacznie identyfikowalne hash-id) i oznacza, gdzie znajdują się gałęzie źródła.

Alice następnie pracuje nad swoim repozytorium, angażując się we własne repozytorium i decyduje się na wprowadzenie zmian:

         a…   b…   c…
origin   o<---o<---o
                   ^ master

              "what'll happen after a push?"


         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                   ^origin/master

Rozwiązanie jest raczej proste, jedyne, co originrepozytorium musi zrobić, to wziąć wszystkie nowe wersje i przenieść swoją gałąź do najnowszej wersji (która git nazywa „przewijaniem do przodu”):

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                             ^origin/master

Przypadek użycia, który zilustrowałem powyżej, nawet nie musi niczego scalać . Tak naprawdę problem nie dotyczy scalania algorytmów, ponieważ algorytm scalania trójstronnego jest prawie taki sam między wszystkimi systemami kontroli wersji. Problem dotyczy bardziej struktury niż czegokolwiek innego .

A co powiesz na przykład, który ma prawdziwe połączenie?

Trzeba przyznać, że powyższy przykład jest bardzo prostym przypadkiem użycia, więc zróbmy znacznie bardziej pokręcony, aczkolwiek bardziej powszechny. Pamiętasz, że originzaczęło się od trzech wersji? Cóż, facet, który to zrobił, nazwał go Bob , pracował sam i dokonał zmian w swoim repozytorium:

         a…   b…   c…   f…
bob      o<---o<---o<---o
                        ^ master
                   ^ origin/master

                   "can Bob push his changes?" 

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

Teraz Bob nie może wypchnąć swoich zmian bezpośrednio do originrepozytorium. System wykrywa to poprzez sprawdzenie, czy wersje Boba bezpośrednio pochodzą od wersji origin, co w tym przypadku nie. Każda próba wypchnięcia spowoduje, że system powie coś w stylu „ Uh… Obawiam się, że nie mogę pozwolić ci to zrobić, Bob ”.

Więc Bob musi włączyć się, a następnie scalić zmiany (z git pull; lub hg pulli merge; lub bzr merge). Jest to proces dwuetapowy. Najpierw Bob musi pobrać nowe wersje, które skopiują je z originrepozytorium. Widzimy teraz, że wykres jest rozbieżny:

                        v master
         a…   b…   c…   f…
bob      o<---o<---o<---o
                   ^
                   |    d…   e…
                   +----o<---o
                             ^ origin/master

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

Drugim krokiem procesu ściągania jest połączenie rozbieżnych wskazówek i zatwierdzenie wyniku:

                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+
                             ^ origin/master

Mamy nadzieję, że scalanie nie spowoduje konfliktów (jeśli ich przewidujesz, możesz wykonać dwa kroki ręcznie w git przy pomocy fetchi merge). Później należy ponownie wprowadzić te zmiany origin, co spowoduje szybkie scalenie do przodu, ponieważ zatwierdzenie scalania jest bezpośrednim potomkiem najnowszego w originrepozytorium:

                                 v origin/master
                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

                                 v master
         a…   b…   c…   f…       1…
origin   o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

Istnieje inna opcja scalenia w git i hg, zwana rebase , która przeniesie zmiany Boba do najnowszych zmian. Ponieważ nie chcę, aby ta odpowiedź była bardziej szczegółowa, pozwolę ci zamiast tego przeczytać na ten temat dokumenty git , mercurial lub bazar .

W ramach ćwiczenia dla czytelnika spróbuj dowiedzieć się, jak to będzie działać z innym zaangażowanym użytkownikiem. Robi się to podobnie jak powyższy przykład z Bobem. Scalanie między repozytoriami jest łatwiejsze niż mogłoby się wydawać, ponieważ wszystkie zmiany / zatwierdzenia są jednoznacznie identyfikowalne.

Istnieje również kwestia wysyłania łat między poszczególnymi programistami, co było ogromnym problemem w Subversion, który jest łagodzony w git, hg i bzr dzięki unikalnie identyfikowalnym wersjom. Gdy ktoś połączy swoje zmiany (tj. Wykona zatwierdzenie scalenia) i wyśle ​​je wszystkim pozostałym w zespole do konsumpcji poprzez wypchnięcie do centralnego repozytorium lub wysłanie łatek, wówczas nie muszą się martwić o scalenie, ponieważ to już się stało . Martin Fowler nazywa ten sposób pracy rozwiązłą integracją .

Ponieważ struktura różni się od Subversion, dzięki zastosowaniu DAG, umożliwia rozgałęzianie i scalanie w łatwiejszy sposób nie tylko dla systemu, ale także dla użytkownika.

Spoike
źródło
6
Nie zgadzam się z twoim argumentem == hałas. Wiele gałęzi nie dezorientuje ludzi, ponieważ główny programista powinien powiedzieć ludziom, z której gałęzi skorzystać, aby uzyskać duże funkcje ... więc dwóch deweloperów może pracować na gałęzi X, aby dodać „latające dinozaury”, 3 może działać na Y, aby „pozwolić ci rzucać samochody przy ludziach ”
Mr. Boy
16
John: Tak, w przypadku niewielkiej liczby gałęzi hałas jest niewielki i można nim zarządzać. Ale wróć po tym, jak zobaczyłeś ponad 50 gałęzi i tagów w subwersji lub wyraźnym przypadku, w którym większość z nich nie możesz stwierdzić, czy są aktywne, czy nie. Problem użyteczności z boku narzędzi; dlaczego wszystkie te śmieci są w twoim repozytorium? Przynajmniej w p4 (ponieważ „obszar roboczy” użytkownika jest zasadniczo gałęzią poszczególnych użytkowników), git lub hg masz opcję, aby nie informować wszystkich o zmianach, które wprowadzasz, dopóki nie podasz ich wcześniej, co jest bezpieczne- pilnuj, kiedy zmiany dotyczą innych.
Spoike
24
Nie rozumiem też, że zbyt wiele gałęzi eksperymentalnych jest argumentem hałasu, @Spoike. Mamy folder „Użytkownicy”, w którym każdy użytkownik ma swój własny folder. Tam może rozgałęziać się tak często, jak chce. Oddziały są niedrogie w Subversion i jeśli zignorujesz foldery innych użytkowników (dlaczego i tak miałbyś się nimi przejmować), to nie zobaczysz hałasu. Ale dla mnie łączenie się w SVN nie jest do bani (i robię to często i nie, to nie jest małe projektu), więc może zrobię coś złego;) Niemniej jednak połączenie Git i Mercurial jest lepsze i dobrze to zauważyłeś
John Smithers
11
W svn łatwo jest zabijać nieaktywne gałęzie, wystarczy je usunąć. Fakt, że ludzie nie usuwają nieużywanych gałęzi, a zatem tworzenie bałaganu, to tylko kwestia porządku. Równie łatwo możesz skończyć z wieloma tymczasowymi oddziałami w Git. W moim miejscu pracy używamy katalogu najwyższego poziomu „temp-oddziały” oprócz standardowych - oddziały osobiste i oddziały eksperymentalne wchodzą tam zamiast zaśmiecać katalog oddziałów, w którym przechowywane są „oficjalne” wiersze kodu (nie użyj gałęzi funkcji).
Ken Liu,
10
Czy to znaczy, że z subwersji w wersji 1.5 można przynajmniej połączyć się tak dobrze, jak git?
Sam
29

Historycznie, Subversion był w stanie wykonać proste dwukierunkowe scalenie, ponieważ nie przechowywał żadnych informacji o scalaniu. Wymaga to przyjęcia zestawu zmian i zastosowania ich do drzewa. Nawet w przypadku informacji o scalaniu jest to wciąż najczęściej stosowana strategia scalania.

Git domyślnie korzysta z 3-kierunkowego algorytmu scalania, który polega na znalezieniu wspólnego przodka łączących się głów i wykorzystaniu wiedzy, która istnieje po obu stronach scalania. Dzięki temu Git jest bardziej inteligentny w unikaniu konfliktów.

Git ma również wyrafinowany kod umożliwiający wyszukiwanie nazw, co również pomaga. To nie przechowywać Zestawienia zmian lub przechowywać wszelkie informacje śledzenia - po prostu zapisuje stan plików na każdy popełnić i używa heurystyki, aby zlokalizować Zmienia nazwę i ruchy kodu wymagane (przechowywanie na dysku jest bardziej skomplikowany niż ten, ale interfejs przedstawia się w warstwie logicznej bez śledzenia).

Andrew Aylett
źródło
4
Czy masz przykład, że svn ma konflikt scalania, ale git nie?
Gqqnbig,
17

Mówiąc prosto, implementacja scalania jest wykonywana lepiej w Git niż w SVN . Przed wersją 1.5 SVN nie rejestrował operacji scalania, więc nie był w stanie wykonywać przyszłych scaleń bez pomocy użytkownika, który musiał podać informacje, których SVN nie zarejestrował. Z 1.5 stało się to lepsze, a model pamięci SVN jest nieco bardziej wydajny niż DAG Gita. Ale SVN przechowywał informacje o scaleniu w dość zawiłej formie, która pozwala scaleniom zajmować znacznie więcej czasu niż w Git - zaobserwowałem czynniki 300 w czasie wykonywania.

Ponadto SVN twierdzi, że śledzi zmiany nazw w celu ułatwienia łączenia przeniesionych plików. Ale w rzeczywistości nadal przechowuje je jako kopię i oddzielną akcję usuwania, a algorytm scalania wciąż się nad nimi potyka w sytuacjach modyfikacji / zmiany nazwy, to znaczy, gdy plik jest modyfikowany w jednej gałęzi, a nazwa w drugiej, a te gałęzie są do połączenia. Takie sytuacje nadal będą powodować fałszywe konflikty scalania, aw przypadku zmian nazw katalogów nawet prowadzą do cichej utraty modyfikacji. (Ludzie SVN zwykle zwracają uwagę, że zmiany są nadal w historii, ale to nie pomaga, gdy nie są w wyniku scalenia, w którym powinny się pojawić.

Z drugiej strony Git nawet nie śledzi nazw, ale rozpoznaje je po fakcie (w czasie scalania) i robi to dość magicznie.

Reprezentacja scalania SVN ma również problemy; w wersji 1.5 / 1.6 można było automatycznie łączyć się z pniem do gałęzi tak często, jak tylko się podobało, ale scalenie w innym kierunku wymagało ogłoszenia ( --reintegrate) i pozostawienia gałęzi w stanie niezdatnym do użytku. Znacznie później odkryli, że tak naprawdę nie jest tak i że a) --reintegrate można to ustalić automatycznie, i b) możliwe są wielokrotne połączenia w obu kierunkach.

Ale po tym wszystkim (co IMHO pokazuje brak zrozumienia tego, co robią), byłbym (OK, jestem) bardzo ostrożny, aby używać SVN w każdym nietrywialnym scenariuszu rozgałęziania, i idealnie spróbowałbym zobaczyć, co myśli Git wynik scalenia.

Inne punkty przedstawione w odpowiedziach, takie jak wymuszona globalna widoczność oddziałów w SVN, nie mają znaczenia dla scalania możliwości (ale dla użyteczności). Poza tym „Git przechowuje zmiany, podczas gdy sklepy SVN (coś innego)” są w większości nie na miejscu. Git koncepcyjnie przechowuje każde zatwierdzenie jako osobne drzewo (jak plik tar ), a następnie używa dość heurystyk do przechowywania tego wydajnie. Obliczanie zmian między dwoma zatwierdzeniami jest niezależne od implementacji pamięci. Prawdą jest, że Git przechowuje DAG historii w znacznie prostszej formie, niż SVN robi swoje połączenie. Każdy, kto próbuje zrozumieć to drugie, będzie wiedział, co mam na myśli.

W skrócie: Git używa znacznie prostszego modelu danych do przechowywania poprawek niż SVN, a zatem może włożyć dużo energii w rzeczywiste algorytmy scalania, zamiast próbować poradzić sobie z reprezentacją => praktycznie lepszym scaleniem.

Andreas Krey
źródło
11

Jedną z rzeczy, o których nie wspomniano w innych odpowiedziach, a która jest naprawdę dużą zaletą DVCS, jest to, że można zatwierdzić lokalnie przed wprowadzeniem zmian. W SVN, kiedy miałem jakąś zmianę, chciałem się zameldować, a w międzyczasie ktoś już dokonał zatwierdzenia w tym samym oddziale, oznaczało to, że musiałem zrobić svn updatewcześniej, zanim mogłem zatwierdzić. Oznacza to, że moje zmiany i zmiany drugiej osoby są teraz mieszane razem i nie ma sposobu, aby przerwać scalanie (jak za pomocą git resetlub hg update -C), ponieważ nie ma zamiaru wrócić do. Jeśli scalenie nie jest trywialne, oznacza to, że nie możesz kontynuować pracy nad funkcją, dopóki nie wyczyścisz wyniku scalenia.

Ale może to jest tylko zaleta dla osób, które są zbyt głupie, aby używać oddzielnych gałęzi (jeśli dobrze pamiętam, mieliśmy tylko jeden oddział, który był używany do rozwoju w firmie, w której użyłem SVN).

Daniel Kullmann
źródło
10

EDYCJA: Jest to przede wszystkim odpowiedź na tę część pytania:
czy jest to faktycznie spowodowane nieodłącznymi różnicami w działaniu obu systemów, czy też konkretne implementacje DVCS, takie jak Git / Mercurial, mają po prostu bardziej sprytne algorytmy scalania niż SVN?
TL; DR - te konkretne narzędzia mają lepsze algorytmy. Dystrybucja ma pewne zalety w przepływie pracy, ale jest prostopadła do zalet łączenia.
EDYCJA KOŃCOWA

Przeczytałem zaakceptowaną odpowiedź. To po prostu źle.

Łączenie SVN może być uciążliwe, a także kłopotliwe. Ale zignoruj, jak to działa przez minutę. Nie ma informacji, które Git przechowuje lub może uzyskać, których SVN nie przechowuje ani nie może uzyskać. Co ważniejsze, nie ma powodu, dla którego przechowywanie osobnych (czasem częściowych) kopii systemu kontroli wersji dostarczy Ci bardziej aktualnych informacji. Dwie struktury są całkowicie równoważne.

Załóżmy, że chcesz zrobić „jakąś sprytną rzecz”. Git jest „lepszy w”. I jesteś zarejestrowany w SVN.

Przekształć SVN w równoważny formularz Git, zrób to w Git, a następnie sprawdź wynik, być może używając wielu zatwierdzeń, dodatkowych gałęzi. Jeśli potrafisz wyobrazić sobie automatyczny sposób przekształcenia problemu SVN w problem Git, to Git nie ma fundamentalnej przewagi.

Pod koniec dnia pozwoli mi na to dowolny system kontroli wersji

1. Generate a set of objects at a given branch/revision.
2. Provide the difference between a parent child branch/revisions.

Dodatkowo, do łączenia warto również wiedzieć (lub krytycznie)

3. The set of changes have been merged into a given branch/revision.

Mercurial , Git i Subversion (teraz natywnie, wcześniej za pomocą svnmerge.py) mogą dostarczyć wszystkie trzy informacje. Aby zademonstrować coś zasadniczo lepszego w DVC, proszę wskazać czwartą informację, która jest dostępna w Git / Mercurial / DVC niedostępna w SVN / scentralizowanym VC.

Nie oznacza to, że nie są lepszymi narzędziami!

Piotr
źródło
1
Tak, odpowiedziałem na pytanie w szczegółach, a nie w nagłówku. svn i git mają dostęp do tych samych informacji (w rzeczywistości zwykle svn ma więcej), więc svn może robić cokolwiek robi git. Ale podjęli różne decyzje projektowe, więc tak naprawdę nie jest. Dowód na DVC / scentralizowanym jest to, że możesz uruchomić git jako scentralizowany VC (być może z narzuconymi pewnymi regułami) i możesz uruchomić svn rozproszone (ale to całkowicie do bani). Jednak dla większości osób jest to zbyt akademickie - git i hg lepiej rozgałęziają się i łączą niż svn. To naprawdę ma znaczenie przy wyborze narzędzia :-).
Peter
5
Do wersji 1.5 Subversion nie przechowywał wszystkich niezbędnych informacji. Wven z SVN po wersji 1.5 przechowywane informacje są różne: Git przechowuje wszystkich rodziców zatwierdzenia scalania, podczas gdy Subversion przechowuje, które wersje zostały już połączone w oddziale.
Jakub Narębski
4
Narzędzie trudne do ponownego wdrożenia w repozytorium svn to git merge-base. Za pomocą git możesz powiedzieć „rozgałęzienia aib podzielone przy wersji x”. Ale sklepy svn „pliki zostały skopiowane z foo na pasek”, więc musisz użyć heurystyki, aby ustalić, że kopia do paska tworzy nową gałąź zamiast kopiować pliki w projekcie. Sztuczka polega na tym, że wersja w svn jest zdefiniowana przez numer wersji i ścieżkę podstawową. Mimo że przez większość czasu można założyć „pień”, gryzie on, jeśli faktycznie są gałęzie.
Douglas,
2
Re: „Nie ma informacji, które git przechowuje lub może wyprowadzić, których svn nie przechowuje ani nie może wyprowadzić”. - Odkryłem, że SVN nie pamięta, kiedy wszystko się połączyło. Jeśli chcesz wciągnąć pracę z pnia do gałęzi i iść tam iz powrotem, łączenie może być trudne. W Git każdy węzeł na wykresie wersji wie, skąd pochodzi. Ma do dwóch rodziców i kilka lokalnych zmian. Ufałbym, że Git będzie w stanie połączyć więcej niż SVN. Jeśli połączysz się w SVN i usuniesz gałąź, historia gałęzi zostanie utracona. Jeśli połączysz się w GIT i usuniesz gałąź, wykres pozostanie, a wraz z nim wtyczka „obwinianie”.
Richard Corfield,
1
Czy nie jest tak, że git i mercurial mają wszystkie niezbędne informacje lokalnie, podczas gdy svn musi patrzeć zarówno na dane lokalne, jak i centralne, aby uzyskać te informacje?
Warren Dew
8

SVN śledzi pliki, podczas gdy Git śledzi zmiany treści . Jest wystarczająco sprytny, aby śledzić blok kodu, który został refaktoryzowany z jednej klasy / pliku do innej. Używają dwóch kompletnych różnych podejść do śledzenia twojego źródła.

Nadal intensywnie używam SVN, ale jestem bardzo zadowolony z tego, że kilka razy korzystałem z Gita.

Niezła lektura, jeśli masz czas: dlaczego wybrałem Git

used2could
źródło
To też czytam i na to liczyłem, ale w praktyce nie działa.
Rolf
Git śledzi zawartość plików, wyświetla zawartość tylko jako zmiany
Ferrybig
6

Wystarczy przeczytać artykuł na blogu Joela (niestety jego ostatni). Ten dotyczy Mercurial, ale tak naprawdę mówi o zaletach rozproszonych systemów VC, takich jak Git.

Dzięki rozproszonej kontroli wersji część rozproszona nie jest tak naprawdę najciekawszą częścią. Interesujące jest to, że systemy te myślą o zmianach, a nie o wersjach.

Przeczytaj artykuł tutaj .

rubayeet
źródło
5
To był jeden z artykułów, o których myślałem przed opublikowaniem tutaj. Ale „myśli w kategoriach zmian” to bardzo niejasny, marketingowo brzmiący termin (pamiętaj, że firma Joela sprzedaje teraz DVCS)
Mr. Boy,
2
Myślałem, że to również było niejasne ... Zawsze myślałem, że zestawy zmian są integralną częścią wersji (lub raczej wersji), co mnie zaskakuje, że niektórzy programiści nie myślą o zmianach.
Spoike
Jeśli szukasz systemu, który naprawdę „myśli o zmianach”, sprawdź Darcs
Max
@Max: jasne, ale kiedy przychodzi push, Git dostarcza tam, gdzie Darcs jest tak samo bolesny jak Subversion, jeśli chodzi o faktyczne połączenie.
tripleee
Trzy wady Git to: a) nie jest tak dobry dla plików binarnych, takich jak zarządzanie dokumentami, gdzie jest bardzo mało prawdopodobne, że ludzie będą chcieli rozgałęzić się i scalić b) zakłada, że ​​chcesz sklonować WSZYSTKO c) przechowuje historię wszystkiego nawet w klonie do często zmieniających się plików binarnych powodujących wzdęcie klonowania. Myślę, że scentralizowany system VCS jest znacznie lepszy dla tych przypadków użycia. Git jest znacznie lepszy do regularnego rozwoju, szczególnie do łączenia i rozgałęziania.
locka