Библиотека сайта rus-linux.net
Архитектура Mercurial
Глава 12 из книги "Архитектура приложений с открытым исходным кодом", том 1.
Оригинал: "Mercurial".
Автор: Dirkjan Ochtman
Перевод: Vlad http://vlad8.com/
12.3. Механизм контроля версий
Теперь, когда вы знакомы с лежащими в основе моделями данных и структурой кода на низком уровне, давайте перейдем на более высокий уровень и рассмотрим, как в Mercurial реализованы концепции контроля версий.
12.3.1. Ветки
Ветки используются повсеместно для разделения различных направлений разработки, которые позже будут интегрированы. Это может быть необходимо, если кто-то экспериментирует с новым подходом, чтобы у нас всегда оставалась главное направление разработки в доступном виде (“ветки для новых функций”), или для того, чтобы быстро выпускать релизы с исправлениями для старых версий (“поддерживающие ветки”). Оба подхода часто используются и поддерживаются всеми современными системами контроля версий. В то время как неявные ветки являются распространенными в системах на основе направленного ациклического графа, именованные ветки (такие, где имя ветки хранится в метаданных изменений) не столь распространены.
Изначально, в Mercurial не было способа явно указывать имена веток. Вместо этого ветки создавались путем создания новых копий и их раздельной публикации. Такой путь эффективен и легок для понимания, он особенно полезен для веток нового функционала, потому что накладные расходы на эти операции не велики. Однако в больших проектах создание копий может быть довольно затратным: так как хранилище репозитория привязано к файловой системе, создание отдельной рабочей копии является медленным процессом и может потребовать большое дисковое пространство.
Из-за этих недостатков, в Mercurial был добавлен второй способ создания ветвей: добавление имени ветки в метеданные изменения. Появилась команда branch, с ее помощью вы можете задать имя ветки для текущей рабочей директории, тогда это имя будет использовано для коммита следующего изменения. Обычная команда update может быть использована для обновления имени ветки; изменение, закоммиченное в ветке, всегда будет привязано к конкретной ветке. Этот подход называется именованные ветки. Однако, прошло несколько релизов Mercurial прежде чем появилась поддержка закрытия таких веток (закрытие скрывает ее из списка веток). Закрытие реализовано путем добавления дополнительного поля в метаданные изменения, в котором записывается, что данное изменение закрывает ветку. Если у ветки более, чем одно направление, все они должны быть закрыты перед тем, как ветка исчезнет из списка веток репозитория.
Конечно, существует более чем один способ реализации веток. В Git используется другой способ наименования веток: при помощи ссылок. Ссылки — это имена, указывающие на другой объект в истории Git, обычно на изменение. Это означает, что ветки в Git эфемерные: как только вы убираете ссылку, информация о том, что ветка когда-то существовала, исчезает без следа; это похоже на то, что вы получаете, когда используете отдельную копию Mercurial и объединяете ее обратно с другой точной копией. Это позволяет очень легко и без затрат манипулировать ветками локально, и предотвращает перегруженность списка веток.
Этот способ создания веток оказался очень популярным, гораздо более популярным, чем именованные ветки или клоны веток в Mercurial. Это привело к созданию расширения bookmarksq, которое, вероятно, будет добавлено в Mercurial в будущем. Оно использует простой неверсионный файл для отслеживания ссылок. Сетевой протокол, используемый для обмена данными в Mercurial, был расширен для добавления возможности передачи информации о ссылках.
12.3.2. Тэги
На первый взгляд то, как в Mercurial реализованы тэги, может быть несколько странным. Когда вы в первый раз добавляете тэг (используя команду tag) в репозиторий будет добавлен и закоммичен файл .hgtags. Каждая строка в этом файле содержит идентификатор узла изменения и имя тэга для него. Таким образом, файл тэгов обрабатывается также, как и любой другой файл в репозитории.
На это есть три важные причины. Первая состоит в том, что необходимо иметь возможность изменять тэги; случаются ошибки и нужно, чтобы их можно было исправить или удалить. Вторая, тэги должны быть частью истории изменений: важно видеть, когда был создан тэг, кем и по какой причине, или даже когда тэг был изменен. Третья причина: нужно иметь возможность добавить тэг к изменению, имевшем место в прошлом. Например, некоторые проекты активно тестируют эталон релиза из системы контроля версий до того, как выпустить его.
Все эти свойства легко возможны при наличии данной архитектуры с файлами .hgtags. Хотя некоторые люди не понимают наличия файлов .hgtags в своих рабочих копиях, такие файлы делают интеграцию механизма тэгирования с другими частями Mercurial (например, синхронизацию с другой копией репозитория) очень простой. Если бы тэги существовали вне дерева исходных кодов (как в Git, к примеру), был бы необходим отдельный механизм для контроля источников тэгов и решения конфликтов от дублированных тэгов. Даже несмотря на то, что последняя ситуация не является очень частой, хорошо иметь такую архитектуру, когда подобные проблемы даже не возникают.
Чтобы все это работало правильно, Mercurial только один раз добавляет новые строки в файл .hgtags. Это также облегчает операцию слияния, если тэги были созданы параллельно в разных копиях. Более новый идентификатор узла для каждого конкретного тэга всегда имеет преимущество, а добавление нулевого идентификатора узла (представляющего пустую корневую версию, которая является общей для всех репозиториев) приведет к удалению тэга. Mercurial также принимает во внимание тэги из всех веток в репозитории, используя анализ, какие из них более новые, для определения их порядка.
Продолжение статьи: Общая структура.