2004 г.
CVS - система управления версиями
Алексей Махоткин, squadette.ru
Эта статья была впервые опубликована в журнале "Программист", номер 2 за 2001 год.
Запрещается перепечатка этой статьи без письменного разрешения автора.
Внимание: в целом статья устарела. Новые инсталляции CVS делать не следует, нужно использовать как минимум Subversion, или другие альтернативы.
<epigraph>
From: luke@jet.msk.su
Message-ID: <huuwvr9t1rz.fsf@jet.msk.su>
Практика показывает, что 99% программистов под ОС Уиндоуз ведут
разработку программ очень странными способами -- про version control
они даже не догадываются, правят по живому, раз и навсегда. На
просьбу вернуться к предыдущей версии хлопают глазами и говорят "а мы
уже всё переправили!". В общем, культура программирования там в массе
своей на уровне африканской деревни.
</epigraph>
Введение
Системы управления версиями - класс программных продуктов, нацеленных на решение ряда задач, с которыми повседневно сталкивается каждый программист. С помощью систем управления версиями вы следите за изменениями кода вашего программного продукта в ходе его разработки, и можете управлять различными его состояниями: новая версия, работа над которой идет прямо сейчас; старая версия, которую придется поддерживать еще некоторое время; или же старая версия, интересная только историкам.
Программисты, чьи исходники контролируются системой управления версиями, чем-то неуловимо отличаются от остальных программистов. Они в каждый момент рабочего дня точно знают, что именно было сделано за день, а после исправления ошибки могут точно сказать, в каком именно месте кода была ошибка. Они не подвержены синдрому "работает - не трогай", потому что могут совершенно безболезненно ударяться в самые сложные эксперименты со своей программой. Они твердо знают, что в любой момент могут вернуться к "исходникам, которые работали", сколько бы экспериментов с новым кодом не было проведено. Более того, если пользователь вдруг захочет небольшое, крошечное изменение, когда программа находится в многообещающем, но совершенно нерабочем состоянии, то все, что для этого потребуется -- переключиться на стабильную ветку, исправить там, что надо и отдать пользователю, затем переключиться обратно на ствол разработки.
В этой статье речь пойдет о CVS (Concurrent Versions System) – одной из систем управления версиями, существующих на рынке. Я впервые начал использовать CVS около трех лет назад, программируя на Delphi, но имея довольно плотный опыт работы под Linux. С тех пор я сменил область деятельности на программирование для Web, участвовал в проектах с несколькими разработчиками, и использовал CVS в каждом своем проекте, сколь бы невелик он был, и даже сколь мало он ни был бы связан с собственно программированием. Признаться, сейчас я вообще не представляю себе, как можно программировать, если не контролируешь собственные исходники: даже этот небольшой текстовый файл со статьей уже имеет ревизию 1.1.
В лучших традициях UNIX CVS занимается относительно небольшим, четко определенным кругом задач, и делает это хорошо. Когда вы начнете использовать CVS, то заметите, что она совершенно не "настаивает" практически ни на чем, включая сам факт своего использования. Все, что вы обнаружите -- один служебный подкаталог в каждом каталоге вашего проекта, и куча преимуществ и услуг, которые предоставит CVS, если дать ему эту возможность.
Повседневное использование
Если ваша операционная система - Linux, то, скорее всего, CVS уже установлена на вашей машине или же может быть установлена в мгновение ока с помощью менеджера пакетов. Если вы используете Windows, то сходите на http://www.cvsgui.org/, и скачайте там клиента и графическую оболочку к нему (если хотите). Создайте репозиторий, руководствуясь инструкциями из обширной документации к CVS.
Теперь начнем создавать где-нибудь в отдельном каталоге (не каталоге с репозиторием!) рабочую копию. Создадим каталог для нашего проекта:
$ cvs co -l .
$ mkdir hello
и поместим его в репозиторий:
$ cvs add hello
Directory /home/cvsroot/hello added to the repository
Создадим внутри этого каталога файл с нашей программой:
=== hello.c ===
#include
int main() {
printf("hello world\n");
}
=== hello.c ===
и поместим этот файл под контроль версий:
$ cvs add hello.c
cvs add: scheduling file `hello.c' for addition
cvs add: use 'cvs commit' to add this file permanently
Проверим, что программа компилируется и выполняется. У нас появилась первая ревизия, вполне пригодная к помещению в репозиторий. Сделаем же это:
$ cvs commit -m "First revision" hello.c
RCS file: /home/cvsroot/myproject/hello.c,v
done
Checking in hello.c;
/home/cvsroot/myproject/hello.c,v <-- hello.c
initial revision: 1.1
done
Отлично. Теперь притворимся, что мы долго и трудно работали, исправляя
грамматику сообщения, которое выводит на экран наша программа, и в результате наш исходник
начинает выглядеть так:
=== hello.c ===
#include
int main() {
printf("Hello, world!\n");
}
=== hello.c ===
Что же изменилось? Спросим у CVS:
$ cvs diff -u hello.c
Index: hello.c
===============================================
RCS file: /home/cvsroot/myproject/hello.c,v
retrieving revision 1.1
diff -u -r1.1 hello.c
--- hello.c 2001/01/23 22:16:35 1.1
+++ hello.c 2001/01/23 22:19:08
@@ -1,5 +1,5 @@
#include
int main() {
- printf("hello world\n");
+ printf("Hello, world!\n");
}
Вот в таком вот формате ("унифицированном diff-формате") CVS показывает нам изменения, произошедшие с файлом с того момента, когда он последний раз "фиксировался" в репозиторий. Легко видеть, что одна строка в файле была изменена: мы видим ее старое и новое состояния. Теперь, когда приветствием, выводимым программой, будет доволен любой корректор, можно зафиксировать и это изменение с помощью все той же команды:
$ cvs commit -m "Improved greeting" hello.c
Описание команд CVS выходит за рамки этой небольшой статьи, но в конце ее приведены ссылки на материалы, в которых эта тема обсуждается с недостижимой здесь полнотой. Я же вернусь к более абстрактному описанию сосуществования с системой контроля версий. Первое время, довольно продолжительное, можно безболезненно работать с буквально полудесятком команд CVS:
- добавление файла в проект (cvs add);
- удаление его из проекта при помощи команды cvs remove (заметьте, что вся история изменений
в этом файле будет сохранена!);
- просмотр изменений (cvs diff);
- фиксация изменений в репозитории (cvs commit);
- на должность пятой команды в данном случае претендуют почти все остальные команды
в зависимости от личных предпочтений.
Для получения максимального эффекта от использования CVS следует соблюдать определенную дисциплину. Фиксирование изменений должно происходить каждый раз, когда наличествует это самое изменение, четко определенное и завершенное.
Например, самый распространенный случай: исправлена ошибка. Следует просмотреть изменения (в этот момент вас могут поджидать самые любопытные сюрпризы, например, после многочасовой отладки вдруг может выясниться, что все изменение свелось к двум строкам в двух разных файлах, хоть вы и редактировали десяток этих файлов в поисках ошибки). Теперь нужно зафиксировать изменение, причем обязательно документировать его: CVS запустит для вас редактор и предложит ввести журнальное сообщение. Если вы вдобавок пользуетесь системами отслеживания ошибок (а это тема для отдельной статьи), то журнальное сообщение – отличное место, куда можно вписать номер исправленной ошибки или, например, ссылку на письмо, в котором пользователь сообщил об исправленной ошибке.
Старайтесь не фиксировать несколько ошибок одновременно (еще хуже в качестве журнального сообщения писать "Исправлено несколько ошибок" или "Куча исправлений"). В то же самое время есть еще одна часто встречающаяся ситуация: предположим, что вы несколько часов писали новый довольно большой модуль, он в основном работает, и осталось внести буквально несколько изменений (или, например, уже поздно и пора идти домой). В этом случае можно смело фиксировать недоделанный файл, а в качестве комментария ставить "почти работает". Оставшиеся доделки чрезвычайно удобно будет внести уже в новую ревизию, используя команду просмотра изменений относительно "почти работающей версии". По крайней мере, к ней всегда можно будет вернуться.
Несколько ветвей разработки
Через несколько месяцев, когда вы более-менее освоитесь с повседневным
использованием CVS, вам все чаще станут вспоминаться виденные когда-то в документации
и в речи старших товарищей словосочетания "стабильная ветка", "сольем изменения на ствол", "поддержка старых версий". Это означает, что вы уже готовы программировать одновременно две версии своей программы. Одна - стабильная, которая уже работает у заказчика, но время от времени требует небольших исправлений или доработок. Вторая - та, разработку которой вы продолжаете, которая будет называться версией 2.0, содержит новые возможности или вообще почти полностью переписана. На помощь приходит CVS, которая с самого начала разрабатывалась для поддержки нескольких ветвей разработки программы.
В какой-то момент вы объявляете, что выпущена Hello Version 1.0. Дистрибутив программы отправлен пользователю, а вам самое время приготовиться к дальнейшей разработке. Пометьте текущее состояние исходников:
$ cvs rtag HELLO-1-0-RELEASE hello
Во-первых, теперь вы всегда сможете вернуться к состоянию программы на момент релиза
с помощью команды
$ cvs co -r HELLO-1-0-RELEASE hello
Во-вторых, что важнее, теперь вы сможете создать ветку разработки, в которой будете
вести поддержку программы (выпуская версии 1.01, 1.02 и т. д.). Для этого используется
команда cvs rtag с ключом -b:
$ cvs rtag -b -r HELLO-1-0-RELEASE HELLO-1-0 hello
Теперь в вашей текущей рабочей копии можно продолжать активную разработку Hello Version
2. Одновременно с этим от пользователя начнут поступать запросы на исправление ошибок, небольшие доработки etc. Создайте себе еще одну рабочую копию в каталоге hello-support:
$ cvs co -r HELLO-1-0 -d hello-support hello
Эта рабочая копия "помнит" о том, что при ее извлечении использовался
идентификатор ветки (HELLO-1-0), и теперь все исправления, которые вы сделаете и зафиксируете, окажутся именно на ветке, не затрагивая основной ствол разработки. И наоборот, изменения, вносимые в вашу основную рабочую копию, не окажут влияния на ветки, которые существуют в репозитории.
Несколько разработчиков
CVS изначально разрабатывалась с учетом возможности работы над проектом нескольких разработчиков. Дело в том, что вы можете извлечь из одного репозитория несколько рабочих копий -- по одной на каждого программиста. Очевидно, что в большинстве случаев разные программисты будут работать над разными частями проекта. Каждый из них будет фиксировать изменения в своей части проекта, и они не станут натыкаться друг на друга в репозитории. Для того чтобы получить изменения, сделанные другими, нужно специально вызвать команду
$ cvs update
Если вдруг случайно Петя и Вася бросятся исправлять один и тот же кусок кода, и сделают это по-разному (сама по себе эта ситуация указывает на недостаток общения Пети и Васи друг с другом), то CVS обработает и эту ситуацию. Когда Петя зафиксирует свое исправление, CVS позволит ему сделать это. Когда Вася попытается зафиксировать свой вариант исправления, CVS обнаружит, что эти исправления перекрываются, и предложит ему обновить рабочую копию с помощью cvs update. Эта команда покажет, что в исправляемом файле произошел так называемый "конфликт" и пометит место конфликта в рабочей копии этого файла. Предположим, Петя решил, что важнее исправить синтаксис выводимого сообщения, а Вася -- что нужно использовать более простую функцию puts(). Конфликт будет выглядеть примерно так:
<<<<<<<<
printf("Hello, world!\n");
=========
puts("hello world!");
>>>>>>>>
Васе следует обсудить с Петей причину конфликта, договориться, какое из изменений важнее (или просто объединить их), затем убрать индикаторы конфликта (строчки из символов "больше", "меньше" и "равно"), оставить лучший из двух вариантов и, если нужно, зафиксировать окончательное изменение.
Многие пугаются, услышав о полуавтоматической обработке конфликтов. На самом деле практика показывает, что при совместной работе с использованием CVS конфликтов практически не возникает (я говорю на основании опыта двухмесячной работы трех программистов над одним проектом). За эти два месяца я наблюдал, ну может быть, три или четыре конфликта. Все они были простейшими и исправлялись за три минуты. Никаких проблем, связанных с совместной работой, замечено не было.
Заключительная часть
CVS необычайно широко применяется при разработке подавляющего большинства современных проектов с открытым исходным текстом. Среди огромного списка операционных систем и программ: FreeBSD, XEmacs, XFree86, OpenSSL, выделяется, пожалуй, лишь ядро Linux, главный разработчик которой, Линус Торвальдс, в силу особенностей личности отказывается использовать какую бы то ни было систему управления версиями, кроме собственного мозга. Да и то, почти все остальные участники разработки держат свой собственный CVS-репозиторий, которым активно пользуются при разработке (здесь им помогает интересная возможность CVS: т. н. "ветки поставщика" (vendor branches)). Проект http://sourceforge.net/, обеспечивающий свободно доступную инфраструктуру для разработчиков свободного программного обеспечения, в качестве стандартной возможности предоставляет использование своего CVS-сервера. Вообще, количество инсталляций и пользователей -- одно из значительных преимуществ CVS.
Альтернативы
На рынке свободно распространяемых программ CVS практически нет конкурентов. Однако из-за почтенного возраста (первые версии CVS появились в 1986 г.) появилась небольшая, но ясно видная ниша для конкурирующих продуктов. Дело в том, что CVS не поддерживает несколько удобных (некоторые даже считают их критичными) возможностей, например, версионность каталогов - отслеживание истории файлов с учетом их переименования, а также поддержку "наборов изменений" (changesets). Кроме того, разработка CVS в последнее время несколько приостановилась, в нем давно не появляется новых крупных возможностей (впрочем, это не означает, что существующих возможностей не хватает). Есть несколько коммерческих продуктов, поддерживающих примерно тот же набор возможностей, что и CVS. Два, на мой взгляд, самых известных - это Perforce (http://www.perforce.com/) и Rational ClearCase (http://www.rational.com/). В конце статьи приведена ссылка на каталог, содержащий ссылки на большое количество систем управления версиями.
В настоящий момент активно ведется разработка того, что когда-нибудь
придет на смену CVS: http://subversion.tigris.org/. Этот проект, Subversion, разрабатывается с учетом положительных сторон CVS, у него новое, не страдающее от "старческих болезней", дерево исходников, некоторые из его разработчиков в прошлом участвовали в разработке CVS. Конечно же, Subversion будет распространяться с исходными текстами и по свободной лицензии. Я очень надеюсь, что этому проекту будет сопутствовать успех! Но в любом случае CVS будет использоваться еще очень и очень долго.
Ссылки на дополнительную информацию
Домашняя страница CVS: http://www.cvshome.org/
Основной ресурс по CVS на Open Directory:
http://dmoz.org / Computers / Software / Configuration_Management / Tools / Concurrent Versions System /
Крупнейший ресурс по CVS на русском языке (документация, статьи, список рассылки):
http://alexm.here.ru/cvs-ru/
Графический (а также обычный текстовый) CVS-клиент под Win32:
http://www.cvsgui.org/
CVS-сервер под Win32:
http://www.cvsnt.org/
Ссылки на другие системы управления версиями:
http:// dmoz.org / Computers / Software / Configuration_Management / Tools/