Сравнение DVCS - несколько задач
Данная статья является очередным сравнением популярных DVCS — Mercurial, Git и Bazaar, с точки зрения нескольких нетривиальных задач.
Работа с SVN (миграция и синхронизация)
Mercurial: отлично! Есть несколько расширений — hgsubversion, hgsvn, convert, позволяющих работать с Subversion тем или иным образом, и не совместимых друг с другом. Самое вменяемое из них — hgsubversion, хотя и заявлено, что оно ещё сырое, и, к сожалению, не распространяется вместе с Mercurial’ом. Имеет фактически весь необходимый функционал — можно делать и push, и pull в/из Subversion, можно клонировать SVN-репозиторий с сохранением веток и меток (правда, обязательно стандартное их расположение в корневых поддиректориях /trunk, /branches, /tags), эти два метода совместимы, rebase также работает, а граф ветвлений сохраняется.
Остальные два экстенжна «нинужны»: hgsvn — нечто более старое, работает сбоку от общего механизма, тоже позволяет делать push и pull, но не клонирует весь репозиторий, а только извлекает (checkout’ит) последнюю версию, чтобы далее можно было использовать Subversion и Mercurial вместе. Ну и конечно, оно не совместимо с hgsubversion. convert же предназначен для конвертации истории проекта из нескольких различных систем контроля версий в Mercurial, ни черта не совместим ни с hgsvn, ни с hgsubversion и не сохраняет граф ветвлений. Зато, правда, поддерживает возможность использования других имён поддиректорий trunk/branches/tags.
Git: очень хорошо (5-)! git-svn встроен в git и умеет всё, что нужно: клонирование, синхронизация (fetch, pull или merge), фиксация изменений в Subversion-репозиториях (dcommit) и rebase работают с сохранением веток и меток, причём стандартная схема их именования trunk/branches/tags не является обязательной. Ветки SVN импортируются как Remote Tracking Branches, что тоже удобно — можно начинать историю ветки в git’е не с сотворения миров, а с любого момента. Также git-svn поддерживает подключаемые внешние репозитории Subversion (т. н. Externals). Граф ветвлений, вроде-бы, сохраняется. На одном из SVN-репозиториев почему-то не сохранился. На тестах же всё получалось… Короче говоря, функционал полон, но возможно, есть баг.
Bazaar: хорошо. Можно импортировать репозиторий командами svn-import или branch, можно делать push и pull в/из Subversion. При импорте можно сохранить все ветки и метки в одном хранилище (если использовать Shared Repository), для этого также требуются стандартные названия trunk/branches/tags. Кроме того, я наткнулся на некоторые проблемы при фиксации изменений в Subversion после нескольких слияний двух Bazaar’овских веток, и пока не разрешил их. Граф ветвлений Subversion, увы, не сохраняется. Также существует несколько других расширений для импорта Subversion в Bazaar, но все они ещё хуже.
Что ещё любопытно — с Subversion-репозиториями DVCS работают, как правило, гораздо быстрее самого Subversion, и быстрее всех работает Bazaar. То есть, в принципе, можно вообще жить с Subversion-сервером и Bazaar-клиентом.
Управление патчами
Первое, что приходит на ум — это, конечно, аналоги quilt'а, работающие поверх DVCS: Mercurial Queues, Bazaar Loom, StGIT. Все они очень похожи и друг на друга, и на сам quilt.
quilt вещь банальная, позволяющая автоматизировать тупое накатывание последовательности большого числа патчей и правку патча, который находится где-то в середине: можно откатить N верхних патчей, внести изменения в файлы и сказать refresh, и верхний на данный момент патч (то есть патч откуда-то из середины) обновится, дабы соответствовать внесённым изменениям. quilt создан на основе скриптов человека, который не использует системы контроля версий — Эндрю Мортона (Andrew Morton) — второго по значимости участника разработки ядра Linux после Линуса Торвальдса.
Из реализаций quilt поверх DVCS появился именно MQ и долгое время, судя по всему, был «изюминкой» Mercurial’а, хотя на самом деле неидеален — идея добавления и удаления истории из/в репозиторий всё-таки странновата, а патчи не хранятся в том же репозитории, что и код — то есть, при клонировании исчезают.
Крут ли quilt, нет ли — каждый решает сам для себя. Конечно, поддержке Debian-патчей на какой-нибудь Midnight Commander (их там в районе 60-и) quilt … помогает. Тем не менее, с моей точки зрения, некорректно закладываться на жёстко последовательное применение всех патчей. На самом деле, такие патчи логично организовывать в виде графа (графа зависимостей). Сразу будет видно, что большинство патчей независимы друг от друга, а зависимости окажутся на виду.
Таким образом, задачу управления патчами удобнее всего решать, заводя по отдельной ветке на каждый патч. Причём даже есть расширения Mercurial pbranch (от patch branches) и Git TopGit (от topic branches). Для Bazaar’а, увы, таких расширений нет.
Схема управления рабочими копиями
Что нам предлагают централизованные системы контроля версий? Некий «хардкод»: репозиторий ровно один, рабочих копий много. Что нам предлагают DVCS? Теоретически, полный беспредел, то есть свободу.
На практике — не совсем полную.
Mercurial говорит нам: на ровно 1 рабочую копию ровно 1 репозиторий, и иначе быть не может. Это и удобно — сказал hg up ветка_такая_то, пара файлов поменялась, и опа — ты уже в другой ветке. Это и неудобно — чтобы положить на диск одновременно две разных ветки, нужно обязательно клонировать репозиторий (поддержки checkout нет).
С Git'ом ситуация почти такая же, как и с Mercurial’ом. 1 рабочая копия, 1 репозиторий. Хотя при клонировании данные репозитория можно и не копировать, задавая опцию --shared, но это скорее похоже на Bazaar’овские Stacked Branches, чем на Lightweight Checkout. Идея лёгких рабочих копий (или «идея .gitlink») высказана для GSoC-2007, однако пока так и не реализована.
Bazaar вначале был хуже всех, а потом стал лучше всех. Вначале он говорил нам: на 1 ветку ровно 1 рабочая копия и ровно 1 репозиторий. А когда исправился, стало можно создать Shared Repository с опцией --no-trees, а потом сколько захочется рабочих копий checkout'ами. Переключить рабочую копию с ветки на ветку также можно — командами switch или qswitch.