Перевод статьи Эрика Синка (Eric Sink) — DVCS and DAGs (Part 1 and Part 2).
Прим. переводчика: В этой статье я буду использовать оригинальные англоязычные сокращения DVCS и DAG для обозначения распределённых систем контроля версий (Distributed Version Control System — DVCS) и направленных ацикличных графов (Directed Acyclic Graph — DAG).
Есть две категории людей:
Я один из первых. :-)
Есть две категории систем контроля версий:
Традиционные инструменты (такие как Subversion и Vault) тяготеют к ведению истории как Линии. В DVCS (таких как Git и Mercurial) история — это DAG. Разница между этими двумя моделями довольно интересна.
Линейная модель испытана и работает. История — это последовательность версий, одна за другой.

Чтобы создать новую версию необходимо:
Люди любят линейную модель за её простоту. Она даёт точный ответ на вопрос, какая версия является последней.
Но у линейной модели есть одна большая проблема: вы можете создать новую версию только в том случае, если она основана на последней версии. И часто случается следующее:

Линейная модель истории не позволит мне создать версию 5 так, как показано на картинке. Вместо этого я буду вынужден получить изменения, сделанные от 3-ей к 4-й версии, и «слить» их со своей версией.
Очевидный вопрос: Что случится, если мы разрешим зафиксировать 5-ю версию на основе 3-ей? Наша история перестанет быть Линией. И превратится в DAG.
А почему мы должны это делать?
Основным преимуществом DAG-модели в том, что она не прерывает разработчика в тот момент, когда он пытается зафиксировать результат своей работы. В этом плане DAG — это, возможно, более точное отражение того, что реально происходит в команде, практикующей параллельную разработку (здесь использован не совсем точный перевод термина «concurrent development», в котором акцент делается на том, что параллельно производимые разработчиками изменения часто делаются в одном и том же коде и часто конфликтуют — прим. пер.). Версия 5 была основана 3-ей, так почему бы не отразить этот факт?
Правда, выясняется, что есть причины этого не делать. В этом графе мы не знаем, какая версия «последняя». И это приводит ко множеству проблем:
Да, это печальная картина. Мир, такой, каким мы его знаем, буквально рушится у нас на глазах.
Дабы избежать сосуществования собак и кошек в состоянии непрерывной массовой истерии, средства, использующие DAG-модель ведения истории, делают всё возможное, чтобы помочь нам разрешить путаницу. Ответ тот же, что и для линейной модели — нам нужно слияние (merge). Но вместо того, чтобы требовать от разработчика делать слияние перед фиксацией изменений, мы позволяем сделать это слияние позднее.

Кому-то требуется создать версию, включающую все изменения, сделанные в версиях 4 и 5. Когда эта версия будет зафиксирована, она будет содержать стрелки, указывающие на обеих её «родителей».
Порядок восстановлен. Мы снова знаем, какая из версий «последняя». Если кто-нибудь вспомнит о том, что надо бы перезагрузить нашего менеджера, он скорее всего тут же сообразит, что этот граф выглядит почти как линия. И за исключением того, что между версиями 3 и 6 случилось что-то непонятное и запутанное, это и есть Линия. Но самое лучшее для нашего менеджера — сильно не переживать по этому поводу.
Чего этот менеджер не знает, так это того, что данный конкретный кризис — мелочь. Он думает, что его старая парадигма полностью разрушена, но в один прекрасный день он придёт в офис и обнаружит вот это:

&@#!
И что теперь?
Если вы живёте в рамках линейной модели, этот граф для вас — абсолютный кошмар. У него ЧЕТЫРЕ оконечных узла. Всё, что требует понимания того, какая версия является последней, обречено на провал, включая вышеописанного менеджера, который сейчас, вероятно, свернулся калачиком в своём кабинете и надеется, что мама не забыла положить ему любимые печенюшки к макаронам.
Линейная модель выглядит в такие моменты весьма привлекательной. И это хорошее обоснование того, что 99,44% разработчиков используют SCM-средства, основанные на линейной модели ведения истории (да, я выдумал эту статистику).
Но всё же, несмотря на весь этот очевидный хаос, мы должны напомнить себе об основном преимуществе DAG-модели: она более точно описывает реальный ход дел в работе программиста. Она не заставляет разработчиков прогибаться под свои желания, как это делает линейная модель. Когда разработчик хочет что-то зафиксировать — он это делает. И DAG попросту записывает ровно то, что действительно произошло.
Многие команды всегда будут предпочитать линейную модель. И в этом нет ничего плохого. Жизнь проще при таком подходе.
Но для некоторых других команд DAG-модель может оказаться весьма полезной. А каким-то командам она вообще может достаться «в нагрузку». Просто потому, что им потребуется использовать DVCS по каким-то иным причинам. DVCS-средства используют DAG-модель потому, что у них нет выбора. Если мы не можем предполагать наличия постоянного соединения с центральным сервером, у нас нет другого пути и мы не можем заставить разработчиков вписывать всю свою работу в линейную модель.
Поэтому нам нужно найти пути, как управляться с DAG. И как же нам быть?
Один из вариантов — это реструктурировать каждую операцию. Если вы говорите доктору «это настоящая пытка, когда возникает необходимость определить последнюю версию», доктор скажет вам «прекратите пытаться это делать». Вместо этого всегда точно указывайте, какой узел использовать:
Я не говорю, что этот подход целесообразен. Я всего навсего хочу заметить, что он теоретически корректен. До тех пор, пока вы в состоянии точно указать узел, который вы хотите использовать, каждая из этих операций может быть выполнена.
Но как нам указать узел? Одно из обстоятельств, которое делает этот подход проблематичным, — это то, что эти узлы часто имеют сложные имена. К примеру, в Git имя узла — это что-то вроде e69de29bb2d1d6434b8b29ae775ad8c2e48c5391. Разработчики находят такой способ именования не слишком интуитивно-понятным.
Все DVCS-средства используют DAG. И все они делают много разных вещей, чтобы-либо предотвратить «кризис множественных оконечных узлов», либо помочь команде управляться с этим. Но все они делают это немного по-своему.
К счастью, это даёт мне удобную возможность разделить их все на 2 группы:
На первую часть этой статьи я получил два вида заслуживающих внимания отзывов (Эрик Синк, автор оригинальной статьи, опубликовал её в двух частях с разницей во времени в одну неделю, чем и объясняется наличие реакции читателей отдельно на её первую часть — прим. пер.):
Прежде, чем начать вторую часть, позвольте кратко ответить на оба этих отзыва.
Да, моя компания (SourceGear, — прим. пер.) разрабатывает систему контроля версий (Vault), основанную на линейной модели ведения истории. Поэтому любая DVCS — это, в определённой степени, прямой конкурент моему продукту.
Я прекрасно сознаю, что нарушаю целый ряд правил:
Моя мама с лёгкостью подтвердит, что я не всегда хорошо соблюдаю правила:-)
Просто дело в том, что я нахожу эту тему интересной. Я проработал в индустрии контроля версий более десяти лет. Я пишу книгу на эту тему. Вот что я делаю. Вот что мне интересно.
На самом деле.
Но здесь происходит нечто большее, чем просто я в роли капиталистического мятежника.
Фанаты Git, вам стоит немного остыть.
Серьёзно, ярые защитники Git делают этот мир непригодным для жизни. Git в самом деле отличная штука, но просто он не является правильным выбором во всех без исключения ситуациях.
В их защиту надо признать, что в этом вопросе яблоко от яблони упало недалеко. Когда люди начинают интересоваться DVCS, одной из первых вещей, на которую они натыкаются, становится видео с презентацией Линуса Торвальдса о Git, записанное в 2007-м году. И там они видят человека, который, кажется, тоже этого не понимает.
Парни, Subversion — это, возможно, самое популярное на данный момент средство контроля версий в мире. Без малого каждый, кто использует систему контроля версий сегодня, использует ту, что основана на линейной модели ведения истории. И они используют эти средства успешно и продуктивно. Когда кто-то отказывается признавать какую-либо пригодность этой модели, они выглядят неумными.
Видео Торвальдса наделало много вреда. Такая позиция — это большое разочарование для людей, интересующихся тем, что нового появляется в мире контроля версий.
Поэтому, мои дорогие почитатели Git, если вы пытаетесь предостеречь людей от использования DVCS и хотите быть уверенными в том, что они не изменят своим сегодняшним подходам, тогда можете продолжать в том же духе, у вас отлично получается.
Но если вы в самом деле хотите помочь миру увидеть преимущества Git и аналогичных средств, тогда осознайте, что люди делали свою работу продуктивно и до их появления.
Эти картинки были нарисованы художником-иллюстратором компании SourceGear, Джоном Вулли (John Woolley), который также создал все иллюстрации к книге комиксов «Evil Mastermind». Всю оформительскую работу и создание иллюстраций для моей готовящейся к выходу книге об управлении исходными кодами также делает Джон.
Тем не менее, поскольку картинки Джона получили гораздо больше похвалы, чем моя «тысяча слов», я решил позлобствовать и отказался включать какие-либо его иллюстрации во вторую часть статьи. :-)
Как я уже говорил в первой части, если DAG-у позволить расти без всякого управления, всё может превратиться в настоящую неразбериху. DAG-и проще создавать. Линии проще использовать. Как только мы начинаем по максимуму использовать DAG-модель, чтобы задействовать все её преимущества, следующее, что сразу же происходит — нам хочется вернуть Линии обратно.
Вот почему в любой DVCS есть возможности, которые могут быть использованы для того, чтобы рост DAG-а был управляемым. Эти возможности придуманы для того, чтобы помешать разработчикам фиксировать изменения, избегая при этом всякой ответственности за порождаемую запутанность, которая растёт каждый раз, когда мы создаём новую точку ветвления.
Другими словами, каждая DVCS содержит возможности, которые позволяют разработчиками взять фрагмент графа и трактовать его как линию.
Git управляет ростом DAG-а путём поддержки именованных веток (branches). Вы лишены возможности зафиксировать изменения, если их «родитель» — не оконечный узел («лист»).
Таким образом, если я использую команду Git checkout, чтобы обновить мою рабочую копию репозитория до узла, не являющегося оконечным, Git проявляет вежливую заботу обо мне:
Если вы фиксируете изменения, всегда основанные только на оконечном узле, то ваша история остаётся очень похожей на линию.
Исторически, Mercurial описывался как поддерживающий только одну ветку на один репозиторий. Сравнения с Git часто фокусировались на очевидном недостатке — отсутствии поддержки ветвления внутри одного репозитория (здесь перевод не соответствует оригинальному тексту, так как в комментариях к статье автор признал наличие опечатки в этом месте, — прим. пер.).
Я говорю в прошедшем времени, так как я слышал, что в Mercurial добавлены некоторые возможности в этой области.
Я упомянул Mercurial здесь, чтобы не оставить и его фанатов в стороне. Я не могу говорить с позиции большого опыта работы с этой системой.
Но всё же я считаю возможным упоминать Mercurial как подтверждение моей точки зрения: в ранних (по меньшей мере) версиях Mercurial управлял ростом графа, препятствуя его ветвлению. К тому же, это способствовало всеобщему восприятию Mercurial как очень простого в использовании средства.
Этот инструмент — это DVCS, которую я использовал больше всего, но я всё же не могу пока считать себя экспертом по ней. По моему опыту, я бы охарактеризовал Bazaar как систему, которая усердно трудится над контролем за ростом DAG-а.
Каждый раз, когда я пытаюсь отправить изменения из моего локального репозитория на центральный сервер, Bazaar требует от меня сделать слияние с другими изменениями из оконечного узла. Ровно так же, как сделала бы любая система с линейной моделью.
Но, что пожалуй здорово, Bazaar даёт мне возможность не использовать центральный сервер, как настоящая DVCS. Но в этом режиме действуют те же самые ключевые ограничения: я не могу зафиксировать какие-либо изменения, если они не основаны на конечном узле в репозитории.
Когда я использую Bazaar, я испытываю ощущение, что использую средство с линейной моделью.
В этом отношении мне ближе всего подход Git к решению этой проблемы.
Bazaar, похоже, верит в то, что ветвление DAG-а допустимо только в том случае, если оно происходит в отдельных экземплярах репозитория, и должно быть устранено прежде, чем изменения из одного репозитория будут перенесены в другой.
Мне нравится способность Git переключать мою локальную копию репозитория через команду «git checkout имя_ветки». Я понимаю, что людям, не привыкшим к постоянной мысли о DAG-е, эта возможность кажется непонятной. Но мне она нравится.
Попрошу заметить, что мне по-прежнему нравятся средства с линейной моделью, такие как Subversion и Vault. Я просто хочу сказать, что средство с DAG-моделью должно действовать похожим образом.
DVCS, которая в последнее время интригует меня больше всего — это Fossil. Она написана Ричардом Хиппом (D. Richard Hipp), создателем SQLite.
У Fossil есть ряд интересных возможностей. Наиболее существенная — это встроенная поддержка баг-трекинга. Это область, в которой все остальные DVCS уступают ей. Они дают вам распределённое управление версиями, но когда приходит время разработчику обновить информацию в баг-трекере, мир снова становится централизованным.
Так или иначе, я пока только лишь начинаю пристально присматриваться к Fossil, но мне нравится как на его сайте описана проблема ветвления:
Прекрасно. В результате у меня создалось впечатление, что Fossil в этом отношении работает аналогично Git. Когда DAG разветвляется, сложность увеличивается.
Прим. переводчика: В этой статье я буду использовать оригинальные англоязычные сокращения DVCS и DAG для обозначения распределённых систем контроля версий (Distributed Version Control System — DVCS) и направленных ацикличных графов (Directed Acyclic Graph — DAG).
Часть 1
Есть две категории людей:
- Те, кто пытается делить всё на две категории.
- Те, кто этого не делает.
Я один из первых. :-)
Есть две категории систем контроля версий:
- Те, в которых история — это Линия.
- Те, в которых история — это Направленный Ацикличный Граф (DAG).
Традиционные инструменты (такие как Subversion и Vault) тяготеют к ведению истории как Линии. В DVCS (таких как Git и Mercurial) история — это DAG. Разница между этими двумя моделями довольно интересна.
Линейная модель испытана и работает. История — это последовательность версий, одна за другой.

Чтобы создать новую версию необходимо:
- Получить последнюю версию.
- Внести изменения.
- Зафиксировать (commit) сделанные изменения.
Люди любят линейную модель за её простоту. Она даёт точный ответ на вопрос, какая версия является последней.
Но у линейной модели есть одна большая проблема: вы можете создать новую версию только в том случае, если она основана на последней версии. И часто случается следующее:
- Я получаю из репозитория последнюю версию. В момент, когда я её получил, это была версия 3.
- Я вношу туда каике-то изменения.
- Пока я это делаю, кто-то создаёт версию 4.
- Когда я собираюсь зафиксировать мои изменения, я не могу этого сделать, так как они не основаны на текущей версии. «Базой» для моих изменений была версия 3, которая была актуальной на тот момент, когда я начал работу.

Линейная модель истории не позволит мне создать версию 5 так, как показано на картинке. Вместо этого я буду вынужден получить изменения, сделанные от 3-ей к 4-й версии, и «слить» их со своей версией.
Очевидный вопрос: Что случится, если мы разрешим зафиксировать 5-ю версию на основе 3-ей? Наша история перестанет быть Линией. И превратится в DAG.
А почему мы должны это делать?
Основным преимуществом DAG-модели в том, что она не прерывает разработчика в тот момент, когда он пытается зафиксировать результат своей работы. В этом плане DAG — это, возможно, более точное отражение того, что реально происходит в команде, практикующей параллельную разработку (здесь использован не совсем точный перевод термина «concurrent development», в котором акцент делается на том, что параллельно производимые разработчиками изменения часто делаются в одном и том же коде и часто конфликтуют — прим. пер.). Версия 5 была основана 3-ей, так почему бы не отразить этот факт?
Правда, выясняется, что есть причины этого не делать. В этом графе мы не знаем, какая версия «последняя». И это приводит ко множеству проблем:
- Предположим, нам нужны изменения в версиях 4 и 5 для выпуска релиза. В данный момент мы не можем этого получить. В системе нет версии, которая включала бы оба набора изменений.
- Наша система сборки настроена на автоматическую сборку последней версии. Что она должна делать в этой ситуации?
- Даже если мы соберём обе версии, 4-ю и 5-ю, какая из них должна быть передана в QA для тестирования?
- Если разработчик хочет обновить своё дерево до последней версии, какую из них ему предпочесть?
- Когда разработчик хочет сделать какие-то изменения, какую версию он должен взять за основу?
- Наш менеджер проекта хочет знать, какие задачи выполнены и сколько работы ещё осталось сделать. Его понимание «сделано» очень тесно связано с понятием «последний». Если он не может понять, какая версия последняя, его мозг плавится в попытках обновить диаграмму Гантта.
Да, это печальная картина. Мир, такой, каким мы его знаем, буквально рушится у нас на глазах.
Дабы избежать сосуществования собак и кошек в состоянии непрерывной массовой истерии, средства, использующие DAG-модель ведения истории, делают всё возможное, чтобы помочь нам разрешить путаницу. Ответ тот же, что и для линейной модели — нам нужно слияние (merge). Но вместо того, чтобы требовать от разработчика делать слияние перед фиксацией изменений, мы позволяем сделать это слияние позднее.

Кому-то требуется создать версию, включающую все изменения, сделанные в версиях 4 и 5. Когда эта версия будет зафиксирована, она будет содержать стрелки, указывающие на обеих её «родителей».
Порядок восстановлен. Мы снова знаем, какая из версий «последняя». Если кто-нибудь вспомнит о том, что надо бы перезагрузить нашего менеджера, он скорее всего тут же сообразит, что этот граф выглядит почти как линия. И за исключением того, что между версиями 3 и 6 случилось что-то непонятное и запутанное, это и есть Линия. Но самое лучшее для нашего менеджера — сильно не переживать по этому поводу.
Чего этот менеджер не знает, так это того, что данный конкретный кризис — мелочь. Он думает, что его старая парадигма полностью разрушена, но в один прекрасный день он придёт в офис и обнаружит вот это:

&@#!
И что теперь?
Если вы живёте в рамках линейной модели, этот граф для вас — абсолютный кошмар. У него ЧЕТЫРЕ оконечных узла. Всё, что требует понимания того, какая версия является последней, обречено на провал, включая вышеописанного менеджера, который сейчас, вероятно, свернулся калачиком в своём кабинете и надеется, что мама не забыла положить ему любимые печенюшки к макаронам.
Линейная модель выглядит в такие моменты весьма привлекательной. И это хорошее обоснование того, что 99,44% разработчиков используют SCM-средства, основанные на линейной модели ведения истории (да, я выдумал эту статистику).
Но всё же, несмотря на весь этот очевидный хаос, мы должны напомнить себе об основном преимуществе DAG-модели: она более точно описывает реальный ход дел в работе программиста. Она не заставляет разработчиков прогибаться под свои желания, как это делает линейная модель. Когда разработчик хочет что-то зафиксировать — он это делает. И DAG попросту записывает ровно то, что действительно произошло.
Многие команды всегда будут предпочитать линейную модель. И в этом нет ничего плохого. Жизнь проще при таком подходе.
Но для некоторых других команд DAG-модель может оказаться весьма полезной. А каким-то командам она вообще может достаться «в нагрузку». Просто потому, что им потребуется использовать DVCS по каким-то иным причинам. DVCS-средства используют DAG-модель потому, что у них нет выбора. Если мы не можем предполагать наличия постоянного соединения с центральным сервером, у нас нет другого пути и мы не можем заставить разработчиков вписывать всю свою работу в линейную модель.
Поэтому нам нужно найти пути, как управляться с DAG. И как же нам быть?
Один из вариантов — это реструктурировать каждую операцию. Если вы говорите доктору «это настоящая пытка, когда возникает необходимость определить последнюю версию», доктор скажет вам «прекратите пытаться это делать». Вместо этого всегда точно указывайте, какой узел использовать:
- Система сборки не собирает последний узел. Вместо этого она собирает ровно тот, который мы ей укажем. Или, может быть, она собирает каждый узел.
- QA тестирует те сборки, которые кто-то считает необходимым протестировать.
- Разработчики не обновляют своё дерево до «последнего». Вместо этого, они смотрят на граф, выбирают узел, и обновляются до него.
Я не говорю, что этот подход целесообразен. Я всего навсего хочу заметить, что он теоретически корректен. До тех пор, пока вы в состоянии точно указать узел, который вы хотите использовать, каждая из этих операций может быть выполнена.
Но как нам указать узел? Одно из обстоятельств, которое делает этот подход проблематичным, — это то, что эти узлы часто имеют сложные имена. К примеру, в Git имя узла — это что-то вроде e69de29bb2d1d6434b8b29ae775ad8c2e48c5391. Разработчики находят такой способ именования не слишком интуитивно-понятным.
Все DVCS-средства используют DAG. И все они делают много разных вещей, чтобы-либо предотвратить «кризис множественных оконечных узлов», либо помочь команде управляться с этим. Но все они делают это немного по-своему.
К счастью, это даёт мне удобную возможность разделить их все на 2 группы:
- Те, которые решают эту проблему тем способом, который мне нравится.
- И те, которые решают эту проблему тем способом, который мне не нравится.
Часть 2
На первую часть этой статьи я получил два вида заслуживающих внимания отзывов (Эрик Синк, автор оригинальной статьи, опубликовал её в двух частях с разницей во времени в одну неделю, чем и объясняется наличие реакции читателей отдельно на её первую часть — прим. пер.):
- Несколько людей обвинили меня в распространении страха, неуверенности и сомнений (в оригинале автор использует распространённую сленговую аббревиатуру FUD — Fear Uncertainly and Doubt, не имеющую прямого аналога в русской речи, — прим. пер.) в отношении линейной модели, потому как я лишь вскользь упомянул о проблемах с DAG-моделью и остановился буквально в шаге от того, чтобы заявить, что DAG-модель может стать лекарством от рака, остановить глобальное потепление и принести мир и спокойствие на Ближний Восток.
- Некоторые люди спрашивали, как я нарисовал такие классные диаграммы.
Прежде, чем начать вторую часть, позвольте кратко ответить на оба этих отзыва.
Мой ответ в защиту DVCS
Да, моя компания (SourceGear, — прим. пер.) разрабатывает систему контроля версий (Vault), основанную на линейной модели ведения истории. Поэтому любая DVCS — это, в определённой степени, прямой конкурент моему продукту.
Я прекрасно сознаю, что нарушаю целый ряд правил:
- Представителям бизнес-общественности, таким как я, не полагается говорить что-либо хорошее о своих конкурентах.
- Наша работа — бояться изменений и распространять этот страх среди других.
- Нам полагается делать вид, что мы не знаем о том, что любой выбор имеет свои побочные эффекты, и утверждать, что наш вариант лучше в любой ситуации.
Моя мама с лёгкостью подтвердит, что я не всегда хорошо соблюдаю правила:-)
Просто дело в том, что я нахожу эту тему интересной. Я проработал в индустрии контроля версий более десяти лет. Я пишу книгу на эту тему. Вот что я делаю. Вот что мне интересно.
На самом деле.
Но здесь происходит нечто большее, чем просто я в роли капиталистического мятежника.
Фанаты Git, вам стоит немного остыть.
Серьёзно, ярые защитники Git делают этот мир непригодным для жизни. Git в самом деле отличная штука, но просто он не является правильным выбором во всех без исключения ситуациях.
В их защиту надо признать, что в этом вопросе яблоко от яблони упало недалеко. Когда люди начинают интересоваться DVCS, одной из первых вещей, на которую они натыкаются, становится видео с презентацией Линуса Торвальдса о Git, записанное в 2007-м году. И там они видят человека, который, кажется, тоже этого не понимает.
Парни, Subversion — это, возможно, самое популярное на данный момент средство контроля версий в мире. Без малого каждый, кто использует систему контроля версий сегодня, использует ту, что основана на линейной модели ведения истории. И они используют эти средства успешно и продуктивно. Когда кто-то отказывается признавать какую-либо пригодность этой модели, они выглядят неумными.
Видео Торвальдса наделало много вреда. Такая позиция — это большое разочарование для людей, интересующихся тем, что нового появляется в мире контроля версий.
Поэтому, мои дорогие почитатели Git, если вы пытаетесь предостеречь людей от использования DVCS и хотите быть уверенными в том, что они не изменят своим сегодняшним подходам, тогда можете продолжать в том же духе, у вас отлично получается.
Но если вы в самом деле хотите помочь миру увидеть преимущества Git и аналогичных средств, тогда осознайте, что люди делали свою работу продуктивно и до их появления.
Мой ответ по поводу тех классных диаграмм
Эти картинки были нарисованы художником-иллюстратором компании SourceGear, Джоном Вулли (John Woolley), который также создал все иллюстрации к книге комиксов «Evil Mastermind». Всю оформительскую работу и создание иллюстраций для моей готовящейся к выходу книге об управлении исходными кодами также делает Джон.
Тем не менее, поскольку картинки Джона получили гораздо больше похвалы, чем моя «тысяча слов», я решил позлобствовать и отказался включать какие-либо его иллюстрации во вторую часть статьи. :-)
ОК, давайте побольше поговорим про графы
Как я уже говорил в первой части, если DAG-у позволить расти без всякого управления, всё может превратиться в настоящую неразбериху. DAG-и проще создавать. Линии проще использовать. Как только мы начинаем по максимуму использовать DAG-модель, чтобы задействовать все её преимущества, следующее, что сразу же происходит — нам хочется вернуть Линии обратно.
Вот почему в любой DVCS есть возможности, которые могут быть использованы для того, чтобы рост DAG-а был управляемым. Эти возможности придуманы для того, чтобы помешать разработчикам фиксировать изменения, избегая при этом всякой ответственности за порождаемую запутанность, которая растёт каждый раз, когда мы создаём новую точку ветвления.
Другими словами, каждая DVCS содержит возможности, которые позволяют разработчиками взять фрагмент графа и трактовать его как линию.
Git
Git управляет ростом DAG-а путём поддержки именованных веток (branches). Вы лишены возможности зафиксировать изменения, если их «родитель» — не оконечный узел («лист»).
Таким образом, если я использую команду Git checkout, чтобы обновить мою рабочую копию репозитория до узла, не являющегося оконечным, Git проявляет вежливую заботу обо мне:
eric$ git checkout 9542b Note: moving to "9542b" which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b HEAD is now at 9542b5f... initial
Если вы фиксируете изменения, всегда основанные только на оконечном узле, то ваша история остаётся очень похожей на линию.
Mercurial
Исторически, Mercurial описывался как поддерживающий только одну ветку на один репозиторий. Сравнения с Git часто фокусировались на очевидном недостатке — отсутствии поддержки ветвления внутри одного репозитория (здесь перевод не соответствует оригинальному тексту, так как в комментариях к статье автор признал наличие опечатки в этом месте, — прим. пер.).
Я говорю в прошедшем времени, так как я слышал, что в Mercurial добавлены некоторые возможности в этой области.
Я упомянул Mercurial здесь, чтобы не оставить и его фанатов в стороне. Я не могу говорить с позиции большого опыта работы с этой системой.
Но всё же я считаю возможным упоминать Mercurial как подтверждение моей точки зрения: в ранних (по меньшей мере) версиях Mercurial управлял ростом графа, препятствуя его ветвлению. К тому же, это способствовало всеобщему восприятию Mercurial как очень простого в использовании средства.
Bazaar
Этот инструмент — это DVCS, которую я использовал больше всего, но я всё же не могу пока считать себя экспертом по ней. По моему опыту, я бы охарактеризовал Bazaar как систему, которая усердно трудится над контролем за ростом DAG-а.
Каждый раз, когда я пытаюсь отправить изменения из моего локального репозитория на центральный сервер, Bazaar требует от меня сделать слияние с другими изменениями из оконечного узла. Ровно так же, как сделала бы любая система с линейной моделью.
Но, что пожалуй здорово, Bazaar даёт мне возможность не использовать центральный сервер, как настоящая DVCS. Но в этом режиме действуют те же самые ключевые ограничения: я не могу зафиксировать какие-либо изменения, если они не основаны на конечном узле в репозитории.
Когда я использую Bazaar, я испытываю ощущение, что использую средство с линейной моделью.
Мои предпочтения
В этом отношении мне ближе всего подход Git к решению этой проблемы.
Bazaar, похоже, верит в то, что ветвление DAG-а допустимо только в том случае, если оно происходит в отдельных экземплярах репозитория, и должно быть устранено прежде, чем изменения из одного репозитория будут перенесены в другой.
Мне нравится способность Git переключать мою локальную копию репозитория через команду «git checkout имя_ветки». Я понимаю, что людям, не привыкшим к постоянной мысли о DAG-е, эта возможность кажется непонятной. Но мне она нравится.
Попрошу заметить, что мне по-прежнему нравятся средства с линейной моделью, такие как Subversion и Vault. Я просто хочу сказать, что средство с DAG-моделью должно действовать похожим образом.
Fossil
DVCS, которая в последнее время интригует меня больше всего — это Fossil. Она написана Ричардом Хиппом (D. Richard Hipp), создателем SQLite.
У Fossil есть ряд интересных возможностей. Наиболее существенная — это встроенная поддержка баг-трекинга. Это область, в которой все остальные DVCS уступают ей. Они дают вам распределённое управление версиями, но когда приходит время разработчику обновить информацию в баг-трекере, мир снова становится централизованным.
Так или иначе, я пока только лишь начинаю пристально присматриваться к Fossil, но мне нравится как на его сайте описана проблема ветвления:
Иметь в дереве более одного оконечного узла обычно считается нежелательным, поэтому обычно ветвлений либо полностью избегают, как на рис. 1, либо быстро устраняют, как на рис. 3 (имеются ввиду рисунки в этой статье, а не на сайте fossil, — прим. пер.). Но иногда кому-то требуется иметь несколько оконечных узлов. К примеру, проект может иметь один конечный узел, который представляет последнюю версию разрабатываемой версии продукта, а второй узел — последнюю «стабильную» (протестированную) версию. Когда несколько оконечных узлов целесообразны — мы называем это ветвлением, а не форком. (Тут важно почувствовать разницу между англоязычными терминами branch и fork. Автор хочет подчеркнуть положительный смысл термина branch (ветка) и в какой-то степени отрицательный характер форка (fork), — прим. пер.).
Прекрасно. В результате у меня создалось впечатление, что Fossil в этом отношении работает аналогично Git. Когда DAG разветвляется, сложность увеличивается.