Чи є різниця між злиттями в svn порівняно з git чи mercurial?


12

З мого розуміння, SVN - це «Легко відділитись». Важко злитися '. Чому так? Чи є різниця, як вони зливаються?

git  svn  mercurial  dvcs 

Відповіді:


21

Будь ласка, дивіться моєї відповіді на переповнення стека щодо дуже конкретної ситуації, коли Mercurial (і Git) зливаються без проблем і де Subversion представляє вам нерівний конфлікт. Ситуація - це простий рефакторинг, зроблений на гілці, де ви перейменовуєте деякі файли.

Що стосується відповіді тадмерів, то тут є низка непорозумінь:

  • Знімки, що належать до Subversion, Mercurial та Git, усіма треками, схожими на сховища проекту. Називання їх версій , редакцій чи наборів змін не має ніякого значення. Всі вони є логічно атомними знімками набору файлів.

  • Розмір ваших комісій не має значення, коли мова йде про об'єднання. Усі три системи зливаються зі стандартним алгоритмом тристороннього злиття, і вхід до цього алгоритму є

    • найбільша поширена версія предків
    • версія на одній гілці
    • версія на іншій галузі

    Не має значення, як були створені дві версії. Ви можете використати 1000 невеликих комітетів з моменту версії предків, або ви можете використати 1 фіксацію. Важливо лише остання версія файлів. (Так, це дивно! Так, багато посібників DVCS мають це жахливо неправильно.)

Він також підкреслює деякі хороші моменти щодо відмінностей:

  • Subversion має деякі «вуду» , де ви можете об'єднати з /trunk, скажімо, на /branches/foo. Mercurial і Git не використовують цю модель - натомість гілки моделюються безпосередньо в історії. Отже історія стає спрямованим ациклічним графіком, а не лінійним. Це набагато простіша модель, ніж та, яку використовує Subversion, і це відрізає ряд кутових випадків.

  • Ви можете легко затримати злиття або навіть дозволити комусь іншому впоратися. Якщо у hg mergeвас виникає багато конфліктів, ви можете попросити свого колегу hg pullвід вас, і тоді він має такий самий стан. Тож він може hg mergeі, можливо, він краще вирішує конфлікти, ніж ти.

    Це дуже складно з Subversion, коли вам потрібно буде оновити, перш ніж ви зможете зробити це. Ви не можете просто ігнорувати зміни на сервері та продовжувати здійснювати свої власні анонімні відділення. Взагалі Subversion змушує вас грати з брудною робочою копією, коли ви svn update. Це щось ризиковано, оскільки ви не зберігали свої зміни в безпечному місці. Git і Mercurial дозволяє спочатку здійснити виконання, а потім оновити та об'єднати за необхідності.

Справжня причина, по якій Git і Mercurial є кращими для злиття, ніж Subversion - це питання реалізації. Існують конфлікти з перейменовуванням, які Subversion просто не може впоратися, навіть думаючи, що зрозуміло, що правильна відповідь. Mercurial і Git справляються з ними легко. Але немає ніяких причин, чому Subversion не впорається з ними, а централізація - це точно не причина.


4
чудова відповідь! Я б схвалив два рази, якби міг. :) Я також додам, що книга SVN, на яку ви посилаєтесь у відповіді SO, прямо визнає, що "функція відстеження злиття Subversion має надзвичайно складну внутрішню реалізацію ..." - це одне досить добре свідчить про те, що функція є ненадійною
gnat

2
... і навіть при надзвичайно складному виконанні не вдасться правильно зрозуміти загального предка в будь-яких, а простих випадках.
Ян Худек

Про затримку злиття - не розумійте цього - з SVN мій колега може оновлюватись до / перевірити магістраль, а потім об'єднатись із моєї гілки в неї.
Gill Bates

@GillBates: Я говорю про ситуацію, коли ви не створили відділення для своєї роботи - коли ви працюєте trunkв SVN. За допомогою DVCS ви можете скористатися без спільного використання, але в SVN ваша svn commitволя безпосередньо вплине на інших, хто працює в одній галузі. Навіть якщо ми вдвох працюємо у філії в SVN, я не можу зробити свою роботу без негайного злиття з вашою роботою. Це робить вчинки дещо страшними - що є страшною властивістю для системи управління версіями! :-)
Мартін Гейслер

6

Основна проблема полягає в тому, що ці системи представляють структуру версій каталогів.

Основна концепція Subversion, навколо якої обертається вся система, - це версія (або, у svn lingo, "перегляд"): знімок файлу в певний момент. Поки історія ідеально лінійна, все добре, але якщо вам потрібно об'єднати зміни з двох незалежних ліній розробки, svn повинен порівняти поточні версії обох, а потім зробити тристоронне порівняння між останньою спільною версією і дві головні версії. Рядки, які з’являються зміненими в одній із голов, а не в іншій, легко вирішити; лінії, які точно однаково відхиляються в обох головах, складніші, але зазвичай виконані; рядки, що відхиляються по-різному, - це те, що змушує svn сказати: "Я не можу цього зрозуміти, людино, будь ласка, виріши це для мене".

На відміну від цього мерзотника і ртутних трекових ревізіями , а не версії. Весь сховище - це дерево наборів змін, кожне з яких залежить від батьків, де батьківський набір змін може мати будь-яку кількість дітей, а корінь дерева представляє порожній каталог. Іншими словами, git / hg говорить "спочатку у мене нічого не було, потім цей патч застосований, потім той патч тощо". Коли вам потрібно об'єднати дві лінії розвитку, git / hg не тільки знає, як виглядає кожна голова в даний момент, і як виглядала остання поширена версія, вона також знає, як відбувся перехід, що дозволяє набагато розумніше об'єднатись.

Інша річ, яка полегшує злиття в DVCS - це опосередкований наслідок розділення понять " фіксація" та " push", а також дозволяти в будь-який час будь-які перехресні злиття між будь-якими двома клонами одного і того ж сховища. За допомогою svn люди, як правило, здійснюють великі набори змін із часто незв'язаними змінами, оскільки фіксація - це також оновлення центрального сховища, яке впливає на всіх інших членів команди; якщо ви скоїте ламану версію, всі будуть гніватися на вас. Оскільки більшість налаштувань передбачає мережевий сервер svn, виконування також передбачає перекачування даних по мережі, а це означає, що вчинення призводить до значної затримки робочого процесу (особливо коли ваша робоча копія застаріла і вам доведеться витягнути спочатку). За допомогою git та mercurial, фіксація відбувається локально, і оскільки обидві дуже ефективні в роботі з локальними файловими системами, вони зазвичай закінчуються миттєво. Як результат, люди (коли вони звикають) здійснюють невеликі додаткові зміни, а потім, коли це працює, натиснути дюжину або близько цього здійснює за один рух. Тоді, коли настає час злиття, СКМ має набагато більш детальну інформацію, яка може пройти, і може зробити кращу роботу щодо вирішення конфліктів безпечно та автоматично.

А потім є приємні деталі, які роблять речі ще простішими:

  • Ви можете мати декілька голів і все одно виконувати будь-яку; На відміну від підривної роботи, вам не потрібно поєднувати потягнення, оновлення та злиття, перш ніж знову здійснити повторне виконання - кілька головок просто залишаються таким чином, поки ви не вирішите об'єднатись.
  • До каталогів не звертаються спеціально; натомість шлях вважається лише одним великим іменем файлу, і всі ваші каталоги повинні бути в той же час переглянуті. Це означає, що ви не можете робити вуду для підривної роботи, коли підпапки проекту знаходяться в різних редакціях, але це також означає, що робоча копія менше шансів стати величезним некерованим зламаним безладом, і що цікавіше, хода не представляється як видалення -and-add (який би повністю порушився у svn, якби не метадодані, що були вдосконалені), а просто як перейменування; якщо перемістити файл, збереглася вся його історія; об'єднання навіть може застосувати зміни до переміщеного файлу, які були внесені до не переміщеної версії того ж файлу після переміщення, в іншій гілці
  • Більшу частину часу вам насправді навіть не потрібно вести: натомість ви просто клонуєте все сховище. Клонування є дешевим, особливо якщо це робиться в одній файловій системі, і якщо ви вирішили хочете позбутися клону, ви просто видалите каталог, в якому він живе, і це все. Для цього вам навіть не потрібно використовувати hg або git.
  • Існує декілька (якщо такі є) обмежень щодо того, що ви можете об'єднати. Ви можете мати шість клонів одного сховища, і об'єднати (а точніше - натиснути або потягнути; явне злиття часто не потрібно) від A до B, потім C до B, потім B до D, потім C до D, B назад до A, D до E, в будь-який час і так часто, як вам подобається.
  • Ви можете перевірити злиття, клонувавши одне із сховищ, які ви хочете об'єднати, а потім витягнувши його в інше. Якщо він робить те, що хочеш, ти можеш відштовхнутися до реальної цілі, якщо цього не відбувається, ви викидаєш клон і починаєш знову.

2
Я маю зазначити деякі виправлення та додає у відповідь: 1. Версії SVN - це глобальне репозиторій , ревізія представляє всі файли репо в якийсь момент 2. Технологія об'єднання в основному поширена у SVN та DVCS - якщо файл у файлах злиття змінив лише таким же чином , злиття створить однакову кількість конфліктів для SVN та DVCS - всі SCM все ще працюють на рівні рядка, а не логічний блок 3. Великі комісії у SVN не є результатом архітектурної слабкості, а тому, що користувачі часто ліниві ідіоти - вони ігнорують основні зразки. Відділення | злиття працює у SVN, якщо / dev / мозок та / dev / hands працюють
Lazy Badger

2
Частина 2: Інтелектуальне злиття в DVCS здебільшого відбувається тому, що, всупереч Subversion, вони відстежують та обробляють переміщення | перейменування файлів, а SVN не робить цього взагалі, таким чином - будь-яка операція, яка обробляє файл, змінюється з одного боку та перейменовується на по-друге, не вдасться. Розгалуження гілками та клонування - це лише різні стратегії розгалуження з однаковими правами на життя, якими користуватися "... залежить від ..."
Ледачий борсук

@LazyBadger: Au contraire. Subversion робить трек рухається / перейменовує, що викликає хибні конфлікти почасти тому , що це звернення з ними перейменувань в злитті просто глючить і частково тому , що є випадки , кутові , які важко або неможливо правильно обробляти. Пізніше, чому git (і ртутний копіював його) за допомогою дизайну не відслідковує перейменування та не вгадує їх під час об’єднання. Що добре працює, якщо вміст все ще достатньо схожий, щоб бути об'єднаним (це коли вам потрібно) і не робить дурних речей інакше.
Ян Худек

@JanHudec - вибачте, SVN-ручка не рухається | перейменовується при атомній одній дії (спосіб DVCS - "перейменувати"), а як "видалити + ...", таким чином - створює конфлікти дерев, де цього не відбувається в DVCS ( справжня перейменування ). Mercurial трек перейменовує явно ( hg mvабо hg addremove --similarity...), тоді як Git використовує евристичні, але обидва обробляють переймена . Я можу отримати конфлікт із деревами навіть з різницею 1 рядка в об'єднаних файлах! Ви повинні знову вивчити деякі аспекти Subversion, вибачте.
Ледачий борсук

5
Зараз ми отримуємо цілком технічні :-) І трек- копії Subversion, і Mercurial , а не перейменування. Обидві системи відстежують, rename a bяк copy a b; remove aі обидві роблять це за один атомний запис. Різниця в поведінці злиття випливає з різного поводження з кутовими справами і від Subversion, що дозволяє більше злиття, ніж Mercurial і Git. Нарешті, Git виявляє перейменування під час злиття та журналу - ми також думаємо додати це в Mercurial.
Мартін Гейслер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.