solovyov.net

Mercurial: введение в распределённые системы контроля версий

6 min read · hg, vcs

Что, почему, для чего?

Примерно года полтора назад я заинтересовался распределёнными системами контроля версий (хотя и слышал о них раньше, обычно о git’e, который в то время под Windows не работал, что мне было критично), когда наткнулся на сайт Bazaar‘a. Подогревали мой интерес обещанные разработчиками блага, в том числе и возможность коммитить без подключения к интернету, но порядочно напрягало то, что передача данных на сервер происходила действительно долго (и даже по локальной сети передача одного коммита занимала несколько секунд).

После нескольких месяцев использования Bazaar’a в своих проектах на каком-то из сайтов я заметил анонс (и немножечко дифирамбов) выхода Mercurial‘a, тоже распределённой системы версий и тоже написанной на Python (тогда это была версия 0.9.4). Дифирамбы эти меня привлекли, и я решил попробовать, и не смог оторваться, настолько система работала быстрее. Её скорость первое время меня поражала, основной набор команд не отличался от привычного мне Subversion’овского, а к графическим интерфейсам я не особо пристрастен, и потому меркуриал быстро и прочно вошёл в мою жизнь. :)

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

Нельзя сказать, чтобы переход был слишком уж гладкий, но за неделю понять режим работы и обучиться работать смогли все (не исключая дизайнеров ;)), и можно сказать, что именно в этот момент я действительно понял, насколько использование такого инструмента повышает качество работы. Об этом можно судить как по отзывам тестировщиков, так и по уменьшившемуся количеству появляющихся за неделю тикетов о проблемах - банально низкокачественные ревизии не пропускались в главный репозиторий.

И мне просто хочется поделиться позитивным опытом использования более продвинутого инструмента, чем применяющийся обычно в разработке сегодня. Но начнётся всё, как обычно, издалека - с самого начала.

Немного истории

Ноги у обеих наиболее популярных сегодня DVCS (Git и mercurial) растут из одного и того же места. ;) Как и положено, таких ног две.

Примерно в то же время, когда стартовал проект по созданию “правильного CVS” -Subversion, было положено начало и другому - Monotone, который был действительно инновационным по сравнению с предшественниками: например, для идентификации ревизий использовался не порядковый номер, а криптографический SHA1-хэш, что позволяет безошибочно определять уникальность каждой ревизии.

Чуть позже, в феврале 2002 года, разработка ядра Linux была переведена с использования диффов и патчей (без войн, естественно, не обошлось) на проприетарную распределённую систему контроля версий BitKeeper, написанную Ларри МакВоем (Larry McVoy). Система, конечно, не безгрешная (и уж явно неудобная для всех, кроме Линуса, тем, что не позволяла посмотреть историю изменений), но работавшая, как говорил Линус, заметно лучше CVS (и его потомков). Хорошо известно высказывание Линуса на тему того, что Subversion -это самый бесцельный проект в истории, учитывая слоган проекта “CVS done right”, так как CVS - изначально порочная концепция.

Всё продолжалось достаточно спокойно до тех пор, пока Эндрю Триджелл (Andrew Tridgell

В ходе активных поисков наиболее подходящим проектом казался Monotone, который имел больше возможностей и потенциала, чем любая другая open source система контроля версий, и всего лишь одну, но очень большую проблему - крайне низкую скорость работы. Так как особенности дизайна Monotone не позволяли его ускорить на несколько порядков (в то время алгоритм добавления файлов имел сложность O(N**3), где N - количество добавляемых файлов), Линус начал разрабатывать Git. Практически одновременно с ним (насколько я знаю, несколько дней разницы в старте - 3 и 6 апреля 2005 года), но до анонса разработки Git’a, другой kernel-hacker, Мэтт Макал (Matt Mackall), начал разрабатывать аналогичную систему (с теми же целями), но на языке Python - Mercurial (только критичные к скорости места, например diff, написаны на C).

Естественно, что с развитием системы её начинало использовать всё больше и больше проектов, и среди реальных мастодонтов, использующих Mercurial в текущий момент в качестве основной системы контроля версий, можно отметить Mozilla, NetBeans, Java (в вики меркуриала можно посмотреть более полный список таких проектов).

Зачем вся эта распределённость

Скорее всего, для большинства людей, особенно успешно использующих централизованные системы контроля версий, остаётся непонятным - зачем было завязывать весь этот сыр-бор с распределённостью и почему нельзя было взять уже стабильную, развивающуюся много лет систему с отличной инфраструктурой в видехостингов, GUI-утилит и т. п., например, Subversion. Тем более, что в распределённых системах постоянно необходимо объединять различные ветки, что, как всем известно ;), довольно трудоёмкая задача.

Однако, если присмотреться поближе, можно увидеть, что у DVCS на текущий момент есть только один недостаток по сравнению CVCS - меньшая распространённость, но очень большое количество преимуществ.

Начну со слияния (merge). Слияние в DVCS - это совсем не то же самое, что объединение веток в SVN. Это аналог svn update, при котором исключена потеря данных - ведь они уже сохранены в ревизиях. Операция простая и не требующая особых усилий, а с хорошей утилитой для мержа вообще превращающаяся в тривиальную.

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

Даёт это ещё порядочный fault tolerance - если что-то случилось с репозиторием, существует куча его бекапов. Собственно, каждый клон - и есть бэкап. :)

Лично для меня одним из самых больших плюсов являлась скорость работы -меркуриал выполняет базовые операции (commit/diff/log/annotate) в несколько раз быстрее SVN, работающего локально. А уж про svn, работащий по сети, можно и не упоминать - с плохим каналом коммиты становятся нудными до смерти, а svn log я вообще предпочитал трогать в крайних случаях. Здесь log занимает до пары десятых секунды в случае, когда кеш файловой системы забит чем-то другим, при этом скорость от размера репозитория скорость зависит линейно (и первые найденные ревизии показываются сразу по нахождению, а не ожидают окончания поиска).

Очень полезна та особенность, что доступ к репозиторию на запись для всех разработчиков не является необходимостью, причём полезна она не только для opensource проектов (где это очевидно, когда есть небольшое количество постоянных разработчиков и людей, время от времени контрибутящих какой-то код), но и для коммерческих. К примеру, право на запись в основной репозиторий имеют только тимлиды, которые делают беглый ревью кода своей команды перед записью, что немало помогает достижению цели неразломанности репозитория. :)

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

План последующих статей

Я планирую опубликовать цикл статей, посвященных Mercurial и DVCS, примерно такого содержания:

If you like what you read — subscribe to my Twitter, I always post links to new posts there. Or, in case you're an old school person longing for an ancient technology, put a link to my RSS feed in your feed reader (it's actually Atom feed, but who cares).

Other recent posts

Server-Sent Events, but with POST
ngrok for the wicked, or expose your ports comfortably
PostgreSQL collation
History Snapshotting in TwinSpark
Code streaming: hundred ounces of nuances