2009-10-19

SCM // 6. Распределенный контроль версий

Сегодня речь пойдет о довольно спорном и в чём-то провокационном вопросе — распределенных системах контроля версий.

Итак, есть проект и в нём — система контроля версий, обслуживающая несколько команд, которые этот проект реализуют. Система контроля версий — одна на всех. Напомню, что я продолжаю серию заметок, и раньше я рассказывал о контроле версий вообще, обойдя конкретные реализации стороной. Так что предметная область тоже постепенно эволюционирует от простого к сложному.



Так вот, в какой-то момент возникает необходимость сделать доступным центральное хранилище локально в одном из центров разработки – для ускорения работы и обхода ограничений по трафику или пропускной способности. Скажем, есть две команды, расположенные территориально в разных местах и часовых поясах – скажем, Дальний Восток России и Центральная временная зона США, их разделяет полмира. Работа идет над одним проектом, и есть необходимость менять одни и те же части продукта. Предположим, что сервер системы контроля версий стоит в США – соответственно, разработчикам в России для создания каждой новой версии приходится отправлять изменения через половину земного шара. Да и любая операция вроде перехода на другую ветку со взятием целиком всей выбранной конфигурации, будет отнимать слишком много времени, учитывая величину пинга. В общем, в подобных ситуациях централизованное хранилище – не самый удобный вариант.

Поскольку проблема не нова и актуальна, со временем были сформулированы разные подходы к решению задачи. А точнее – два подхода к построению распределенных систем контроля.

Открытое распределение – это принцип построения, при котором каждая рабочая копия конфигурации может иметь свой набор дочерних версий и обмен созданными версиями происходит по выбору создателя изменений.

Плюсом подобных систем является то, что работа на отдельной рабочей станции может идти независимо от других экземпляров хранилища. Собственно, хранилища может и не быть – сколько копий, столько и хранилищ. Не удивительно, что подобные системы нашли применение в первую очередь в Open Source. Отсутствие необходимости содержать отдельный сервер дает возможность обмениваться только той информацией, которая нужна, и не перегружать хранилище и трафик той дельтой, которая может кому-то никогда так и не понадобиться.
Минус подобного подхода в том, что обмен дельтой рабочих продуктов плохо поддается централизованному контролю. Получается некоторое броуновское движение дельты, которое многим менеджерам, привыкшим к централизации, может быть не по душе.
Примерами подобных систем могут быть BitKeeper, git, Mercurial (Hg).

Распределение путём репликации предусматривает создание равноценных копий центрального хранилища данных (или его частей) на всех распределенных серверах. Здесь можно провести аналогию с базами данных и их репликацией. Для каждого разработчика хранилище версий, к которому он подключается, является основным. Все версии и ветки создаются в центральном хранилище или реплике. Для распределения данных делается копия хранилища на другие имеющиеся сервера и часть разработчиков переключается на сделанную копию. При необходимости обмена результатами работы, происходит репликация хранилища – оба сервера обмениваются метаинформацией.

Плюсом подобного подхода можно считать централизацию работы в рамках одного местоположения команды. Также стоит добавить, что имеется возможность удерживать часть накопленной информации от синхронизации с другими командами, но в то же время делать её доступной одновременно всей локальной команде. Это бывает важно, когда код разрабатываемых подсистем не должен попадать наружу – даже для других команд, работающих над этим же продуктом.

Минус – необходимость настройки механизмов репликации. Но, как правило, системы, использующие такой подход, предусматривают инструменты эффективного обмена данными. Кроме того, для кого-то может быть минусом тот факт, что все операции с версиями производятся на одном сервере, а не на локальном компьютере разработчика. То есть «распределённость» системы проявляется на уровне команд и их местоположения, но никак не на уровне простого разработчика.
Примерами систем с репликацией служат ClearCase и Perforce.

Оба типа (открытый и репликационный) схожи между собой — в обоих случаях происходит обмен информацией между разными копиями одного множества элементов и их версий. Разница между ними – в «масштабах». В системах с репликацией минимальной единицей реплики, как правило, является репозиторий или его значимая часть, обрабатываемая как единое целое. В системах с открытым распределением минимальная единица обмена информацией – это отдельная версия отдельного элемента.
Для обоих типов распределения характерна общая проблема. Это необходимость введения четкого соглашения об именовании элементов и их веток, а также меток для обозначения полученных конфигураций. При соединении результатов работы не должны получаться разные файлы с одним и тем же именем и метаинформацией (ветками, метками, атрибутами). Поэтому все разработчики и команды, работающие отдельно друг от друга, должны придерживаться общих стандартов. В разных системах бывают предусмотрены механизмы для обеспечения этого условия. К примеру, при работе с ClearCase создаются триггеры на создание любой метаинформации, проверяющие её на соответствие стандарту – для всех создаваемых веток ставится необходимым наличие в имени ветки кода (или идентификатора) того сайта (команды), в котором ветка была создана.

Кроме того, системы с открытым распределением фактически оставляют на усмотрение каждого отдельного разработчика – что он отдаст команде в виде дельты, а что не станет выставлять на общее обозрение. Плохо это или хорошо – зависит от культуры, принятой в рамках проекта. Для более централизованных систем, с репликацией репозитариев, эта проблема видится под другим углом. Когда все обязаны вносить свои изменения в центральную (для своей команды) систему контроля версий, база метаинформации быстро разрастается в размерах – что сказывается как на стоимости хранения, так и на скорости репликации разнесенных в пространстве баз.

Какой из подходов лучше, конечно, нельзя сказать сразу и для всех проектов. Приспосабливать для работы броуновское движение git'а или остановиться на более стабильном состоянии – решать менеджменту каждого проекта. Единого решения для всех команд и проектов нет и быть не может. Кому интересно посмотреть на различия разных систем и моделей – см. ссылку [1].

Кстати, распределенными могут быть не только системы контроля версий, но и системы отслеживания запросов на изменение. Логика работы совершенно аналогична. Вот только основная модель работы – репликационная. Пример – IBM Rational ClearDDTS. Поскольку подобные системы не очень распространены, останавливаться на них подробно не будем.

По традиции, использованные и рекомендуемые для самостоятельного изучения источники:

  1. en.wikipedia.org/wiki/Comparison_of_revision_control_software — сравнение систем контроля версий;
  2. lib.custis.ru/index.php/The_Risks_of_Distributed_Version_Control — трезвый взгляд на риски, связанные с распределенными системами контроля версий;

Порекомендую ещё одну статью о проблемах внедрения разных систем контроля версий:
lib.custis.ru/index.php/Version_Control_and_%E2%80%9Cthe_80%25%E2%80%9D
Немного провокационная, однако стоит прочитать в первую очередь тем, кто относит себя к прогрессивной части программерского сообщества.
И, заранее отвечая на вопрос: нет, я не фанат ни SVN, ни git.

P.S. На отдельной странице собраны ссылки на статьи по основам контроля версий и вообще управлению конфигурациями.

5 комментариев:

  1. Хорошая ссылка (о проблемах внедрения VCS).
    По посту: можно же организовать и с помощью DVCS модель разработки, схожую с централизованной. Когда у каждого есть локальный репозиторий, но все в конце концов сваливается в основную ветку, которая расположена где-то на общедоступном сервере. Можно сделать таких серверов несколько (для каждой команды), а потом обмениваться changeset'ами. Можно применить модель разработки, которую используют для Linux. Есть подсистемы, есть ментейнеры, которые принимают код в эти подсистемы, а затем передают в ветку Линуса.

    ОтветитьУдалить
  2. Конечно, можно организовать *централизованную* модель с помощью распределенных (*децентрализованных*) средств... Но зачем использовать для централизации средства, изначально созданные для ДЕцентрализации? :) Короче, принципиальное противоречие выходит.

    VCS с репликацией справляются с работой больших команд ничуть не хуже, чем разного рода git и Hg.


    А за коммент спасибо :)

    ОтветитьУдалить
  3. Ну, это для менеджеров, которым нужна централизация. При этом сохраняются удобства распределенной системы, связанные, скажем, с ветвлением. Или если нужно быстро кому-то перекинуть изменения со своей ветки, то можно не использовать централизованный репозиторий.
    Централизованный репозиторий будет использоваться для того, чтобы новым членам проекта было проще начать (особенно актуально для Open Source Community).
    Я просто к тому, что распределенные системы, на мой взгляд, могут обеспечить большую гибкость, так как могут использоваться и при децентрализованной модели, и при централизованной (с элементами децентрализованной).

    ОтветитьУдалить
  4. Смысл централизованной модели - именно в том, чтобы всё лежало в одном месте, к которому идёт обращение ото всюду. В статьях, указанных в конце статьи, даются объяснения, зачем оно могло бы пригодиться.

    Поэтому, если выбирается централизованная модель, то руководство проекта хочет именно того, чтобы никакие движения (ветвление, мёрж) не происходило бесконтрольно и в обход центрального репозитория.

    Так что для каждой задачи - свой инструмент :)

    Хотя не спорю, распределенные системы "by design" обладают местами гибкостью, не свойственной централизованным системам.

    ОтветитьУдалить
  5. > Так что для каждой задачи - свой инструмент :)

    С этим трудно не согласиться :)

    ОтветитьУдалить