logo
Проектирование статистического пакета прикладных программ

5. Управление версиями

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

Для решения этой проблемы программисты всего мира достаточно давно используют так называемые системы контроля версий (СКВ, Version Control System, VCS) - программное обеспечение для облегчения работы с изменяющейся информацией. Такие системы наиболее широко используются при разработке программного обеспечения для хранения исходных кодов разрабатываемой программы. Однако они могут с успехом применяться и в других областях, в которых ведётся работа с большим количеством непрерывно изменяющихся электронных документов.

Системы управления версиями делятся на централизованные и децентрализованные (распределённые).

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

Часто бывает, что над одним проектом одновременно работают несколько человек. Если два человека изменяют один и тот же файл, то один из них может случайно отменить изменения, сделанные другим. Системы управления версиями отслеживают такие конфликты и предлагают средства их решения. Большинство систем может автоматически объединить (слить) изменения, сделанные разными разработчиками. Однако такое автоматическое объединение изменений, обычно, возможно только для текстовых файлов и при условии, что изменялись разные (непересекающиеся) части этого файла. Такое ограничение связано с тем, что большинство систем управления версиями ориентированы на поддержку процесса разработки программного обеспечения, а исходные коды программ хранятся в текстовых файлах. Если автоматическое объединение выполнить не удалось, система может предложить решить проблему вручную.

Многие системы управления версиями предоставляют ряд других возможностей:

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

· дают возможность узнать, кто и когда добавил или изменил конкретный набор строк в файле;

· ведут журнал изменений, в который пользователи могут записывать пояснения о том, что и почему они изменили в данной версии;

· контролируют права доступа пользователей, разрешая или запрещая чтение или изменение данных, в зависимости от того, кто запрашивает это действие.

Каждая система управления версиями имеет свои специфические особенности в наборе команд, порядке работы пользователей и администрировании. Тем не менее, общий порядок работы для большинства VCS совершенно стереотипен.

Общие принципы правильного использования VCS немногочисленны и едины для любых разработок и систем управления версиями.

Рисунок 6 - Схема работы централизованных систем контроля версий

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

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

3. Любое значимое изменение должно оформляться как отдельная ветвь. Промежуточные результаты работы разработчика фиксируются в эту ветвь. После завершения работы над изменением ветвь объединяется со стволом. Исключения допускаются только для мелких изменений, работа над которыми ведётся одним разработчиком в течение не более чем одного рабочего дня.

4. Версии проекта помечаются тэгами. Выделенная и помеченная тэгом версия более никогда не изменяется.

Второй тип систем управления версиями - распределённые, известные также как Distributed Version Control System, DVCS. Такие системы используют распределённую модель вместо традиционной клиент-серверной. Они, в общем случае, не нуждаются в централизованном хранилище: вся история изменения документов хранится на каждом компьютере, в локальном хранилище, и при необходимости отдельные фрагменты истории локального хранилища синхронизируются с аналогичным хранилищем на другом компьютере. В некоторых таких системах локальное хранилище располагается непосредственно в каталогах рабочей копии.

Когда пользователь такой системы выполняет обычные действия, такие как извлечение определённой версии документа, создание новой версии и тому подобное, он работает со своей локальной копией хранилища. По мере внесения изменений, хранилища, принадлежащие разным разработчикам, начинают различаться, и возникает необходимость в их синхронизации. Такая синхронизация может осуществляться с помощью обмена патчами или так называемыми наборами изменений (англ. change sets) между пользователями.

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

Рисунок 7 - Схема работы распределенных систем контроля версий

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

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

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

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

В настоящее время наибольшую популярность имеют две таких системы: Git и Mercurial. Также достаточно известны системы Darcs, BitKeeper, Bazaar и Monotone.

Git была создана самим Линусом Торвальдсом для управления разработкой ядра Linux. Первая версия появилась в 2005 году. Примерами проектов, использующих Git, являются ядро Linux, Drupal, Cairo, GNU Core Utilities, Mesa, Wine, Chromium, Compiz Fusion, FlightGear, jQuery и некоторые дистрибутивы Linux. Программа является свободной и выпущена под лицензией GNU GPL версии 2.

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

Mercurial изначально разрабатывалсь для эффективной работы с очень большими репозиториями кода. Mercurial первоначально был написан для Linux, позже портирован под Windows, Mac OS X и большинство Unix-систем.

Основные достоинства Mercurial:

· без проблем работает на Windows и UNIX;

· стабилен;

· имеет большой список возможностей;

· имеет множество утилит для интеграции с разнообразными средами разработки и оболочками (в том числе хорошо интегрируется с MS Visual Studio);

· использует минимум ресурсов;

· имеет множество плагинов.

Система Mercurial написана на Python, хотя чувствительные к производительности части выполнены в качестве Python-расширений на C. Значительное количество проектов по разработке свободного программного обеспечения использует Mercurial в качестве основной системы контроля версий. В их числе: Mozilla, OpenOffice.org, OpenJDK, Netbeans, OpenSolaris, ALSA, Xen.

Mercurial прежде всего консольная программа, но имеет графические оболочки. Большинство пользователей применяют TortoiseHg, что обусловлено её поддержкой авторами Mercurial, возможностью интеграции в проводник Windows и в Gnome/Nautilus, а также сходство с TortoiseSVN. Внешний вид TortoiseHg представлен на рисунке 8.

Рисунок 8 - Интерфейс TortoiseHg