среда, 10 июня 2009 г.

Введение в контроль версий

Предисловие

Контроль версий? А зачем он вообще нужен? Нужен, более того вы всегда используете контроль версий в той или иной степени, даже не подозревая об этом! Контроль версий - это летопись, это история. А история, как известно, - это путеводитель в будущее.

Даже, когда вы работаете в одиночку над статьей или маленькой программой, вы используете контроль версий. Вот только системой контроля версий выступает ваш ум, ваша память.

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

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

Экскурс в историю

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

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

diff -u file_old.txt file_new.txt > file.diff

Затем автор, имея перед глазами результат работы diff, вносил правки в оригинал. Вносил, вносил, вносил... Первому надоело так делать автору программы patch, которая появилась на свет в 1985 году. Эта программа автоматически применяет патч (diff файл) к исходному файлу или каталогу:

patch < file.diff

Несмотря на солидный возраст эти программы до настоящего времени продолжают оставаться актуальными. А любой уважающий себя текстовый редактор умеет работать в diff режиме.

Вернемся к контролю версий. Хранить состояния проекта в виде полных копий слишком накладно, особенно в те далекие времена, когда объемы дисков измерялись килобайтами.
Поэтому в 1985 году используя механизмы работы diff, patch и diff3 создали RCS (Revision Control System), которая для каждого файла хранит самую последнюю версию и набор изменений между состояниями, что позволяет получить любую из предыдущих версий файла.
Однако у RCS был существенный недостаток - она не была предназначена для групповой работы, поэтому на ее основе сделали CVS (Concurrent Versions System). Но у CVS также имелись недостатки, связанные с тем, что CVS работала на уровне файлов, а не на уровне проекта целиком. В связи с этим для замены CVS была разработана более удобная в работе SVN (Subversion).

Азы "садоводства"

Поскольку репозиторий системы контроля версий, в отличии от набора копий проекта, является целостной структурой, чтобы ориентироваться в нем принято ставить метки - этакие маркеры, отмечающие различные состояний, например версии продукта.

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

Рассмотрим пример. Ваша команда, работая на стволе, выпустила первую версию продукта - в репозитории поставили метку RELENG_1_0_REL (RELENG - это сокращение от release engineering) и продолжили работать, двигаясь ко второй версии. В это время в релизе 1.0 обнаруживается досадная оплошность, тогда вы от метки RELENG_1_0_REL, создаете ветку RELENG_1, на которой исправляете ошибку и выпускаете версию 1.1, поставив в репозитории метку RELENG_1_1_REL. Затем оказывается, что одно реализованное на стволе важное новшество можно легко перенести в версию 1.1, так как выход версии 2.0 будет не скоро, вы принимаете решение, выпустить версию 1.2, содержащую это новшество. Для этого необходимые изменения сливаются со ствола на ветку RELENG_1, и с выпуском релиза 1.2 ставиться метка RELENG_1_2_REL.

Кроме вышеупомянутых веток, можно создавать так называемые экспериментальные ветки, на которых обкатываются какие-то уж очень неординарные новшества проекта. Если эти оказались полезными, то код с экспериментальной ветки сливают на ствол, иначе ветку "забрасывают".

Если непосредственно перед релизом требуется дополнительная подготовка, например документации или части исходников, то релиз RELENG_1_0_REL делают не на стволе, а непосредственно на ветке RELENG_1, место отщепления которой маркируют тегом RELENG_1_BP (break point). Этот тег необходим, чтобы, например, можно было посмотреть различия ветки от ствола в момент отщепления.

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

Особенности систем контроля версий

Системы контроля версий можно разбить на два типа: централизованные и распределенные. К централизованным относятся CVS, Subversion (он же SVK), к распределенным - Darcs, Mercurial, Git.

Основные особенности централизованных систем:

1. Все дерево проекта храниться в одном едином репозитории.
2. Можно получить лишь необходимую часть проекта, ветки.
3. Для работы необходимо быть online.

Основные особенности распределенных систем:

1. Каждая ветка проекта обычно - это отдельный репозиторий.
2. Нельзя получить часть проекта - только репозиторий полностью.
3. Можно работать offline.

Рассмотрим подробней каждый из 3 пунктов.

1. У централизованой системы создание ветки - это очень легкая операция, а сами ветки - всего лишь изменения. А у распеределенной системы, чтобы сделать ветку, необходимо создать полноценную копию репозитория. Чтобы минимизировать занимаемое место набор распределенных репозиториев оптимизируют за счет использования жестких ссылок файловой системы. Эту операцию желательно повторять после масштабных слияний между локальными ветками.

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

3. Необходимость быть online при современном развитии коммуникаций можно считать незначительным требованием. Это требование становиться еще мягче, если учесть, что можно работать не со всем репозиторием, а лишь с необходимой частью, Да и самые часто используемые команды: state и diff - можно использовать offline.

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

Если вы используете централизованную систему контроля версий планируете находиться вне сети продолжительное время, то можно перейти в режим создания патчей. К слову, манипулировать патчами удобно при помощи Darcs, который представляет собой скорее систему обмена патчами, нежели систему контроля версий. В крайнем случае, поверх централизованной системы всегда можно сделать распределенную, например SVK поверх SVN.

Подводя итоги, можно сказать, что выбор между централизованной и распределенной системой контроля версий целиком зависит от стиля работы команды. И централизованные, и распределенные системы имеют как преимущества так и недостатки, но ни один из них не является критичным. Совместить достоинства обоих подходов обещают в Subversion 2, добавив некоторые элементы распределенных систем.

Комментариев нет: