Содержание
Простой способ прощупать почву с новым инструментом контроля версий, это поэкспериментировать с переключением существующих проектов, а не начинать новый проект с нуля.
В этом приложении мы обсудим, как импортировать историю проекта в Mercurial, и на что обратить внимание, если вы привыкли к другой системе контроля версий.
Mercurial поставляется с расширением называемым convert
, которое может импортировать историю проекта из наиболее популярных систем контроля версий. В то время когда эта книга была написана, оно могло импортировать историю из следующих систем:
(Чтобы понять, почему Mercurial поддерживает в качестве источника самого себя, смотрите в разделе Раздел A.1.3, «Очистка дерева».)
Вы можете включить расширение в обычном порядке, отредактировав файл ~/.hgrc
.
[extensions] convert =
Это сделает доступной команду hg convert. Команда проста в использовании. Например, эта команда будет импортировать историю Subversion для Nose unit testing framework в Mercurial.
$
hg convert http://python-nose.googlecode.com/svn/trunk
Расширение convert
действует поэтапно. Иными словами, после того как вы выполните hg convert первый раз, запуская его снова вы будете импортировать любые новые ревизии, совершенные после первого запуска. Инкрементные преобразования будут работать только если вы запустите hg convert в том же репозитории Mercurial, который вы использовали, потому что расширение convert
сохраняет некоторые частные метаданные не под контролем системы контроля версий, в файле с именем .hg/shamap
внутри целевого репозитория.
Если вы хотите начать делать изменения, используя Mercurial, то лучше клонировать дерево, в котором вы будете проводить преобразование и оставить оригинальное дерево для последующий инкрементальных преобразований. Это самый безопасный способ позволяет вытягивать и объединять будущие изменения из исходной системы контроля версий в своём новом активном репозитории Mercurial.
Команда hg convert приведенная выше преобразует только историю ветки trunk
репозитория Subversion. Если мы вместо этого используем URL http://python-nose.googlecode.com/svn
, Mercurial автоматически обнаружит trunk
, tags
и branches
, которые обычно используют проекты Subversion, и он будет импортировать каждый как отдельную ветвь Mercurial.
По умолчанию, каждая ветка Subversion импортируется в Mercurial с названием ветки. После завершения преобразования, можно получить список имен активных веток в Mercurial репозитории с помощью hg branches -a. Если вы предпочитаете импортировать ветви Subversion без названия, используйте опцию --config convert.hg.usebranchnames=false
команды hg convert.
Как только вы преобразовывали свое дерево, если вы хотите следовать обычной для Mercurial практике работы в одном дереве, содержащем одну ветку, можно клонировать одну ветку используя hg clone -r mybranchname.
Некоторые средства контроля версий сохраняют только короткие имена пользователей при фиксации, и они могут трудно интерпретироваться. Обычно в Mercurial сохраняется имя коммиттера и адрес электронной почты, который является гораздо более полезным для разговора с ними после факта фиксации.
Если вы преобразовываете дерево из системы контроля версий, которая использует короткие имена, можно сопоставить эти имена с длинными эквивалентами, передавая опцию --authors
команде hg convert. Этот параметр принимает имя файла, который должен содержать записи следующего вида.
arist = Aristotle <aristotle@phil.example.gr> soc = Socrates <socrates@phil.example.gr>
Всякий раз, когда convert
встретит ревизию с именем пользователя arist
в исходном репозитории, он будет использовать имя Aristotle <aristotle@phil.example.gr>
в преобразованной для Mercurial ревизии. Если совпадения не найдется, то имя используется дословно.
Не все проекты имеют чистую историю. Там может быть каталог, который никогда не должен были проверятся, слишком большие файлы, или целая иерархия, которая должна быть переработана.
Расширение convert
поддерживает идею «карты файлов», которая позволяет реорганизовать файлы и каталоги в проекте, при импорте истории проекта. Это полезно не только при импорте истории из других систем контроля версий, но также и для того чтобы подрезать или реорганизовать дерево Mercurial.
Чтобы указать карту файлов, используйте опцию --filemap
и укажите имя файла. Карта файлов содержит строки в следующем формате.
# This is a comment. # Empty lines are ignored. include path/to/file exclude path/to/file rename from/some/path to/some/other/place
Директива include
указывает файл или все файлы в каталоге, которые будут включены в целевой репозиторий. Она также исключает любые другие файлы и директории не включенные явно. Директива exclude
указывает файлы или директории, которые будут исключены, а другие прямо не упоминаемые должны быть включены.
Чтобы переместить файлы или каталог из одного места в другое, используйте директиву rename
. Если вам необходимо переместить файл или каталог из подкаталога в корневой каталог репозитория, используйте .
в качестве второго аргумента директивы rename
.
Часто требуется несколько попыток, прежде чем будет получена идеальное сочетание карты пользователей, карты файлов и других параметров конвертации. Преобразование репозитория subversion через протокол доступа похожий на ssh
или http
может протекать в тысячи раз медленнее, чем Mercurial реально способен работать, из-за задержек в сети. Это делает подбор идеальных настроек преобразования очень тяжелой.
Команда svnsync может значительно ускорить преобразование репозитория Subversion. Она создаёт зеркало только для чтения для репозитория Subversion. Идея заключается в создании локального зеркала вашего Subversion дерева, а затем преобразовании зеркала в Mercurial репозиторий.
Предположим, мы хотим преобразовать репозиторий Subversion для популярного проекта Memcached в Mercurial дерево. Во-первых, мы создаем локальный репозиторий Subversion.
$
svnadmin create memcached-mirror
Далее, мы установим ловушку Subversion необходимую для svnsync.
$
echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change
$
chmod +x memcached-mirror/hooks/pre-revprop-change
Затем мы инициализируем svnsync в этом репозитории.
$
svnsync --init file://`pwd`/memcached-mirror \ http://code.sixapart.com/svn/memcached
Наш следующий шаг — начинаем процесс зеркалирования svnsync.
$
svnsync sync file://`pwd`/memcached-mirror
Наконец, мы импортируем истории нашего локального зеркала Subversion в Mercurial.
$
hg convert memcached-mirror
Мы можем использовать этот процесс инкрементно, если репозиторий Subversion по-прежнему используется. Мы запускаем svnsync для вытягивания новых изменений в наше зеркало, а затем запускаем hg convert для импорта их в наше дерево Mercurial.
Есть два преимущества двухступенчатого импорта с svnsync. Во-первых, используется более эффективная синхронизация кода Subversion по сети, чем при hg convert, так как меньше данных передаётся по сети. Во-вторых, импорт из локального дерева Subversion настолько быстр, что вы можете изменять ваши установки неоднократно без ожидания сетевых процессов каждый раз.
Subversion в настоящее время является самой популярной системой контроля версий с открытым исходным кодом. Хотя есть много различий между Mercurial и Subversion, что делает переход от Subversion на Mercurial не особенно трудным. Обе имеют схожие наборы команд и в целом единый интерфейс.
Основное различие между Subversion и Mercurial, конечно то, что Subversion является централизованной, в то время как Mercurial распределённой. Mercurial хранит всю историю проекта на локальном диске, сеть нужна только если вы хотите явно общаться с другим репозиторием. В отличие от Subversion, которая очень мало информации хранит локально, и таким образом, клиент должен связываться со своим сервером для большинства распространенных операций.
Subversion более или менее может обходится без четко определенного понятия ветви: какая-то часть пространства имён сервера объявляется веткой и является предметом конвенции, с программным ограничением доступа. Mercurial обрабатывает репозиторий в качестве единой ветви управления.
Поскольку Subversion не знает, что части ее пространства имён в действительности ветви, то относится к большинству команд, как запросу работы над любым каталогом в котором вы сейчас находитесь. Например, если вы запускаете svn log, вы получите историю той части дерева, в которой вы находитесь, а не дерева в целом.
Команды Mercurial ведут себя по-другому, по умолчанию они работают со всем репозиторием. Запустите hg log и он расскажет вам историю всего дерева, в какой бы части рабочей директории вы не находились в данный момент. Если вы хотите увидеть историю одного файла или каталога, просто укажите его имя, например, hg log src.
Из моего собственного опыта, это различие в поведение по умолчанию, скорее всего запутает вас, если у вас есть необходимость часто переключаться между двумя инструментами.
В Subversion, это нормально (хотя и несколько неодобрительно) для нескольких пользователей совместно работать в одной ветке. Если Алиса и Боб работают вместе, и Алиса совершает какое-либо изменений в их общей ветке, Бобу необходимо обновить свою рабочую копию прежде чем он сможет фиксировать свои изменения. Так как в это время он не имеет постоянной записи своих изменений, он может повредить или потерять их в ходе или после обновления.
Mercurial использует модель фиксация-потом-слияние. Боб фиксирует свои изменения локально перед вытягиванием изменений, или отправкой их на сервер, который он разделяет с Алисой. Если Алиса отправит ее изменения перед тем как Боб попытается отправить свои, он не сможет отправить свои изменения пока вытянет ее, не выполнит слияние с ними, и не зафиксирует результат слияния. Если он делает ошибку в процессе слияния, он все еще может вернуться к ревизии, в которой записаны его изменения.
Стоит отметить, что это общие методы работы с этими инструментами. Subversion поддерживает безопасную модели работы-в-своей-собственной-ветке, но это достаточно громоздко на практике и не будет широко использоваться. Mercurial может поддерживать менее безопасный режим, позволяющий вытягивать изменения и объединять их поверх незафиксированных изменений, но это считается в высшей степени необычным.
Команда Subversion svn commit немедленно публикует изменения на сервер, где их могут видеть все, кто имеет доступ на чтение.
С Mercurial фиксация всегда локальна, и должна быть опубликована через команду hg push позднее.
Каждый подход имеет свои преимущества и недостатки. Модель Subversion означает, что изменения публикуются и, следовательно могут быть пересмотрены и использованы, немедленно. С другой стороны, это означает, что пользователь должен иметь доступ к фиксации в репозиторий для того, чтобы использовать программное обеспечение в обычном порядке, а доступ к фиксации не легко выдается в большинстве проектов с открытым кодом.
Подход Mercurial позволяет любому, кто может клонировать репозиторий вносить изменения без необходимости каких-либо разрешений, и они могут публиковать свои изменения и продолжать участвовать так как они считают нужными. Различие между фиксацией и публикацией открывает возможность фиксировать изменения на своём ноутбуке и на несколько дней забыть, чтобы потом отправить их, что в редких случаях сотрудник может временно застрять.
Таблица A.1. Команды Subversion и их эквиваленты в Mercurial
Subversion | Mercurial | Примечание |
---|---|---|
svn add | hg add | |
svn blame | hg annotate | |
svn cat | hg cat | |
svn checkout | hg clone | |
svn cleanup | n/a | Очистка не требуется |
svn commit | hg commit; hg push | hg push публикует после фиксации |
svn copy | hg clone | Создание новой ветки |
svn copy | hg copy | Копирование файлов и директорий |
svn delete (svn remove) | hg remove | |
svn diff | hg diff | |
svn export | hg archive | |
svn help | hg help | |
svn import | hg addremove; hg commit | |
svn info | hg parents | Показывает какая ревизия сейчас вытянута |
svn info | hg showconfig paths.parent | Показывает вытянутый URL |
svn list | hg manifest | |
svn log | hg log | |
svn merge | hg merge | |
svn mkdir | n/a | Mercurial не отслеживает каталоги |
svn move (svn rename) | hg rename | |
svn resolved | hg resolve -m | |
svn revert | hg revert | |
svn status | hg status | |
svn update | hg pull -u |
В некоторых системах контроля версий, печать diff для одного зафиксированной ревизии может быть мучительным. Например, в Subversion, чтобы посмотреть, что изменилось в редакции 104654, вы должны ввести svn diff -r104653:104654. Mercurial устраняет необходимость указания ID-ревизии дважды в общем случае. Для простого просмотра используйте hg export 104654. Для сообщения лога и последующего diff hg log -r104654 -p.
При запуске hg status без каких-либо аргументов, он выдает статус всего дерева, с путями относительно корня репозитория. Это делает сложным копирование имени файла из вывода hg status в командную строку. Если вы укажете имя файла или каталога команде hg status, она будет печатать пути относительно вашего текущего местоположения вместо этого. Таким образом, чтобы получить статус всего дерева с помощью hg status, с путями, которые считаются относительно текущего каталога, а не корня репозитория, укажите вывод команды hg root как параметр для команды hg status. Вы легко можете сделать это следующим образом на Unix-подобной операционной системе:
$
hg status `hg root`