Управление исходными текстами. Часть 1. Краткое руководство по CVS

Рыженков Илья

Базовые операции

 

 

Подготовка к работе

Чтобы начать работать с CVS, вам нужно всего ничего – исполняемый модуль (cvs.exe для Windows) и всё! «Что?» - скажете вы: «мне не нужна сеть и выделенный сервер? У меня не будет множества проблем с инсталляцией?». Именно так. CVS вполне может работать на локальной машине, в маленькой домашней сети, в сети компании или обеспечивать совместную разработку множества программистов по всему миру через Интернет. В данной статье мы будем использовать в основном локальный вариант.

 

Установка

Если Вы чувствуете себя комфортно в мире Open Source, можете скачать исходные тексты CVS с официальной web-страницы и собрать его для своей системы самостоятельно. Если же вам удобнее сразу получить исполняемый модуль, особенно если вы используете операционную систему Windows – проще всего взять готовый модуль на странице, посвящённой CVS для Windows . Скачайте архив, называющийся «Precompiled binaries w/o installer», и достаньте оттуда cvs.exe, который следует поместить в каталог, прописанный в каталогах поиска системы (path). Остальные файлы из архива пригодятся, если Вы надумаете устанавливать cvs server на Windows NT/2000/XP.

Вы можете спросить меня, зачем мучиться с командной строкой для работы с CVS, когда можно использовать какую-нибудь оболочку и получить все преимущества графического интерфейса пользователя? Мне кажется, используя оболочки сложнее понять принципы работы, закономерности и, кроме того, затруднительно создать более-менее сложный скрипт для обновления нескольких связанных проектов, их автоматической сборки и запуска набора тестов с последующей отправкой результатов по электронной почте. Тем не менее, я буду указывать, как добиться того же результата с помощью одной из самых популярных оболочек над CVS для Windows – WinCVS, страница которой расположена по адресу .

 

Исполнение команд

Общий синтаксис операций с CVS выглядит так:

> cvs [cvs-options] command [command-options-and-arguments]

ПРИМЕЧАНИЕ. Угловой скобкой в начале строки «>» я буду отмечать текст, набираемый в командной строке. Текст без угловой скобки, следующий за командой, является предполагаемым выводом.

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

ПРЕДУПРЕЖДЕНИЕ. Некоторые ключи имеют одинаковое наименование, но совершенно разный смысл, когда используются как ключи к CVS (cvs –key command) и как ключи к команде (cvs command –key). Будьте внимательны при использовании ключей и располагайте их в правильном месте.

Ключ Описание
-d cvsroot Указать CVSROOT явно. Если не указан, CVS пытается определить CVSROOT из текущего каталога, переменной окружения «CVSROOT» или файла .cvsrc
-q Показывать меньше информации во время работы (quiet). Подавляется дополнительная информация, например о сканировании дерева каталогов.
-Q Показывать еще меньше информации во время работы (really quiet). Выводятся только сообщения об ошибках.
-r Новые файлы, полученные из репозитория, помечаются флагом read-only. Используется для отслеживания редактирования файлов при помощи watchers/editors.
-w Новые файлы, полученные из репозитория, помечаются флагом read-write (включена по умолчанию). Используется для отключения опции –r при использовании переменных окружения или .cvsrc.
-l Не записывать информацию о выполненной команде в журнал (history log). Команда, тем не менее, выполняется, и все изменения файлов отслеживаются.
-n Не производить никаких фактических изменений в рабочем каталоге . Полезно для проверки наличия изменений в репозитории.
-t Показывать детально, что происходит во время операции. Особенно полезно для понимания работы CVS, рекомендуется использовать с ключом –n.
-v Показать версию CVS.
-T tmpdir Использовать tmpdir как временный каталог во время работы.
-e editor Использовать editor для редактирования дополнительной информации, например при отсутствии –m у команд, требующих комментария.
-f Не использовать .cvsrc (файл, в котором можно сохранить постоянно используемые настройки, в этой статье не обсуждается ).
-z #Сжимать данные при передаче по сети (0 – не сжимать, 9 – максимальное сжатие).
-x Шифровать данные при передаче по сети (если поддерживается методом доступа ).
-a Авторизоваться при каждом взаимодействии с сервером (если поддерживается методом доступа ).
-s VAR=VAL Установить пользовательскую переменную для CVS ( в этой статье не обсуждается ).

WINCVS. Можно использовать Admin\Command line… для выполнения команд CVS, набранных вручную.

 

Создание репозитория

Эксперименты проще всего производить с локальным репозиторием. Работа с удаленным CVS мало чем отличается, однако в этом случае Вам должен быть известен правильный CVSROOT. Например, администратор CVS-сервера может создать тестовый репозиторий и сообщить Вам необходимую информацию. Для работы с локальным репозиторием необходимо его проинициализировать самостоятельно. Создайте где-либо пустой каталог и выполните команду инициализации:

> cvs –d :local:c:/cvs/repository init

>

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

В созданном пустом каталоге должен появиться подкаталог «CVSROOT», содержащий некоторое количество управляющих файлов. В этой статье устройство репозитория рассматриваться не будет.

WINCVS. Локальный репозиторий создается командой "Create\Create a new repository…".

 

Создание проекта

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

СОВЕТ Если используется Windows - давайте всем файлам имена в нижнем регистре.

Начните с проекта, состоящего из одного текстового файла. В пустом каталоге с именем “test” создайте файл “readme.txt” следующего содержания:

This is line number one

This is another line of source code

Will CVS automatically save my code each hour? No, but you can schedule automatic commit operation.

Теперь необходимо поместить файл в репозиторий:

cvs -d:local:c:/cvs/repository import -m “Comment string” remote/path vendor release

• Ключ -d со следующим за ним cvsroot, как обычно, задаёт репозиторий.

• Команда import указывает, что текущий каталог необходимо импортировать в репозиторий.

• Необязательный ключ -m со своим аргументом идёт после команды и относится к ней. Он указывает комментарий, который необходимо проассоциировать с данной редакцией. Если не указать комментарий в командной строке, CVS откроет редактор по умолчанию (например, notepad) и попросит вас ввести комментарий.

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

• Далее следуют две метки - поставщик (vendor) и символическое имя версии (release). Эти метки полезны, если вы импортируете исходные тексты сторонних разработчиков или свои проекты, уже имеющие определенную историю и нумерацию версий.

Выполнять эту команду следует из корневого каталога проекта, в этом примере - из каталога “test”.

В нашем случае эта команда может выглядеть так:

› cvs -d:local:c:/cvs/repository import -m “Initial import of the project” test myself initial

N test/readme.txt

No conflicts created by this import

Вывод команды означает, что в репозитории был создан файл для хранения редакций readme.txt в каталоге test, и не произошло никаких неприятностей в процессе работы.

WINCVS Выберите пункт меню "Create\Import module…" Затем выберите каталог, который вы хотите импортировать в репозиторий. Далее появится список типов файлов, обнаруженных в каталоге. Вы можете выбрать, какие из них необходимо импортировать, а какие нет.

Теперь, если краешком глаза заглянуть в репозиторий, можно обнаружить там новый каталог с именем test, внутри которого CVS расположил свои служебные файлы и файлы проекта с информацией о редакциях - проект создан и находится в репозитории. Однако локальный каталог до сих пор не имеет никакого отношения к CVS - файлы всего лишь «скопированы» в репозиторий. Теперь нужно создать структуру, которая бы хранила информацию о связи с репозиторием локально.

ПРЕДУПРЕЖДЕНИЕ Импорт файлов в репозиторий не создаёт локальной структуры с информацией о связи с репозиторием

Чтобы создать связь между репозиторием и рабочим каталогом, необходимо выполнить другую операцию - checkout. Но предварительно нужно… удалить каталог, из которого импортировались файлы. Он больше не нужен, поскольку вся необходимая информация содержится в репозитории. Возможно, неплохой мыслью будет резервное копирование проекта, но в данном случае этого можно не делать. Итак, удалите каталог “test”, из которого производился импорт. Теперь можно произвести операцию получения рабочей копии из репозитория.

 

Получение рабочей копии

Скорее всего, у Вас есть некоторый каталог, где и хранятся разнообразные проекты. Это хороший кандидат для использования в качестве основного каталога для получения рабочих копий проектов из CVS. Предположим для простоты, что это c:\projects\

WINCVS Хорошей мыслью может быть установка этого каталога в качестве корневого для дерева каталогов. Используйте "View\Browse Location\Change…", чтобы установить его. Это избавит Вас от лишней информации во время работы с WinCVS

Установите этот каталог в качестве текущего:

› C:

› cd c:\projects

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

› cvs -d:local:c:/cvs/repository checkout test

cvs checkout: Updating test

U test/readme.txt

• Ключ -d указывает, из какого репозитория забирать файлы.

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

• test указывает путь в репозитории или имя модуля, откуда следует брать файлы.

WINCVS Получить модуль или каталог из репозитория можно, используя команду Checkout module из меню Create. CVSROOT можно настроить в диалоге на вкладке General.

Вывод команды показывает, что произошло обновление файла readme.txt из репозитория. Буква «U» означает, что файл был получен полностью (updated). Теперь у Вас должен был появиться каталог test, в котором находятся ранее импортированный readme.txt и каталог «CVS», содержащий служебную информацию. Обычно там будут находиться 3 файла с именами Entries, Repository и Root. В файле Entries CVS сохраняет информацию о файлах, которыми он управляет, их редакциях и датах обновления. В файле Repository хранится путь к данному каталогу в репозитории относительно CVSROOT. Сам CVSROOT сохраняется в файле Root. Именно потому, что для каждого каталога известен cvsroot и местоположение в репозитории, при работе с проектом указывать их (с помощью ключа -d) нет необходимости. С этого момента у Вас имеется рабочий каталог, связанный с репозиторием. Вся необходимая служебная информация находится в каталогах CVS, которые будут созданы также в каждом подкаталоге, если таковые появятся впоследствии.

Эту же операцию должны проделать и другие участники проекта, если они есть. Заметьте, что команда import выполняется одним человеком и создаёт структуру данных в репозитории. Все участники проекта должны проделать только операцию checkout и сразу получить связанный с репозиторием рабочий каталог.

 

Изменение рабочей копии

Согласитесь, создать проект было не так-то просто, с учётом всех премудростей. Зато с этого момента наступает просто благодать! Никаких специальных действий для редактирования рабочих файлов предпринимать не нужно. Вы просто вносите все необходимые изменения до тех пор, пока результат вас не устроит. По завершении работы результаты отправляются в репозиторий командой commit (см. Отправка изменений в репозиторий). А пока давайте внесем изменения в файл readme.txt, например, удалим последнюю строчку и вставим новую. После изменений readme.txt может выглядеть так:

This is line number one

New line. Appeared after edit.

This is another line of source code

В некоторых случаях всё-таки придётся совершить определённые действия, прежде чем обновлять центральное хранилище. Речь идёт о появлении новых файлов и каталогов, которые пока еще отсутствуют в репозитории. Предлагаю сразу создать новый файл с именем todo.txt:

Do not forget to commit files

Теперь надо сообщить системе управления версиями о появлении нового файла. Для этого используется команда add, которая выполняется из того же каталога, в котором находится новый файл

› cvs add todo.txt

cvs add: scheduling file `todo.txt' for addition

cvs add: use 'cvs commit' to add this file permanently

Файл todo.txt теперь помечен на добавление, но реально он будет помещен в репозиторий при выполнении команды commit, о чём и напоминает вывод этой команды. Вы также можете добавить ключ -m “comment” для указания комментария для добавленного файла. В отличие от многих других команд, в отсутствие ключа -m не будет открыт редактор для ввода комментария, вместо этого комментарий будет считаться пустым.

WINCVS Пометить файл(ы) на добавление в репозиторий можно командой Add selection из меню Modify, предварительно выделив их в списке

Аналогичным образом производится удаление файла - используется команда remove. Команда remove требует отсутствия файла в рабочем каталоге, то есть вы должны сначала удалить файл физически, иначе CVS откажется удалять его из репозитория:

› cvs remove readme.txt

cvs remove: file `readme.txt' still in working directory

cvs remove: 1 file exists; remove it first

Вы можете удалить файл самостоятельно:

› del readme.txt

› cvs remove readme.txt

cvs remove: scheduling `readme.txt' for removal

cvs remove: use 'cvs commit' to remove this file permanently

Или попросить сделать это CVS, используя ключ -f для команды remove

› cvs remove -f readme.txt

cvs remove: scheduling `readme.txt' for removal

cvs remove: use 'cvs commit' to remove this file permanently

Если же после удаления файла вы передумали и решили всё-таки не удалять его, выполнение команды add воскресит файл:

› cvs add readme.txt

U readme.txt

cvs add: readme.txt, version 1.1.1.1, resurrected

WINCVS Чтобы пометить файлы на удаление, воспользуйтесь командой Remove из меню Modify. Удаление локального файла произойдёт автоматически.

Помните, команды add и remove не производят операций с репозиторием (за исключением воскрешения файла), они только помечают их для выполнения операции во время отправки изменений в репозиторий.

 

Отправка изменений в репозиторий

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

› cvs commit -m “comment”

cvs commit: Examining.

Checking in readme.txt;

cvsroot/test/readme.txt,v ‹- readme.txt

new revision: 1.2; previous revision: 1.1

done

RCS file: cvsroot/test/todo.txt,v

done

Checking in todo.txt;

cvsroot/test/todo.txt,v ‹- todo.txt

initial revision: 1.1 done

Ключ -m “comment” задаёт комментарий к изменениям, чтобы впоследствии можно было легко определить, чем именно данная редакция отличается от предыдущей. Поскольку в любой момент можно посмотреть различие в тексте между любыми редакциями, нет смысла указывать, какие строчки добавлены или изменены. Цель комментария - описание результатов работы в целом, а не конкретных изменений. Комментарии являются очень важной частью работы команды, поскольку позволяют другим разработчиком узнать, что именно вы сделали, и скоординировать свою работу соответственно. Если кому-то интересны детали вашей работы, он может заглянуть в код, сравнить редакции и разобраться во внесенных изменениях. В конце концов, он может спросить Вас лично.

ПРЕДУПРЕЖДЕНИЕ CVS не заменяет управления, общения и других процессов, которые должны происходить при совместной разработке программного продукта несколькими участниками. CVS предназначен для отслеживания редакций исходных текстов и централизованного хранения проектных файлов.

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

WINCVS Чтобы отправить файлы в репозиторий, используйте команду Commit из меню Modify

В нашем примере изменился файл readme.txt и добавился файл todo.txt. После выполнения команды commit в репозитории создаётся новый файл для отслеживания редакций файла todo.txt, и текущему его содержимому присваивается номер 1.1. Измененному содержимому файла readme.txt присваивается номер 1.2. Мы по-прежнему можем получить редакцию 1.1 файла readme.txt, если нам это потребуется, но об этом я расскажу чуть позже.

 

Обновление рабочей копии

Если вы - не единственный участник проекта, и одним репозиторием пользуются одновременно несколько человек, то любой из них мог обновить репозиторий. В этом случае для работы с самыми свежими исходными текстами необходимо периодически выполнять операцию обновления рабочего каталога из репозитория. Процесс этот во многом симметричен процессу отправки изменений в репозиторий, хотя имеются и различия. Вы выполняете команду update, и изменения, произошедшие в репозитории, отражаются в рабочих файлах. Однако для того, чтобы посмотреть этот процесс в действии, понадобится еще один рабочий каталог. Чтобы его создать, воспользуйтесь командой checkout с ключом -d из каталога проектов (например, c:\projects):

› cvs -d:local:c:/cvs/repository checkout -d test2 test

cvs checkout: Updating test2

U test2/readme.txt

U test2/todo.txt

ПРЕДУПРЕЖДЕНИЕ Обратите внимание, что ключи -d до и после команды checkout имеют разный смысл. Первый указывает на местонахождение репозитория, а второй указывает, что файлы нужно получить в каталог test2, а не test

После выполнения этой команды будет создан второй рабочий каталог, связанный с тем же репозиторием и теми же файлами в нём. Таким образом, можно внести изменения в одном рабочем каталоге и получить их в другом, некоторым образом эмулируя работу нескольких программистов. Итак, измените в новом рабочем каталоге файл todo.txt (я добавил строчку «Some change» в конец файла) и выполните операцию commit для обновления репозитория:

› cvs commit -m "added line"

cvs commit: Examining.

Checking in todo.txt;

d:\temp\rep/test/todo.txt,v ‹- todo.txt

new revision: 1.2; previous revision: 1.1

done

СОВЕТ Команда cvs status показывает текущее состояние каталога - сообщает, необходимо ли обновление, какие редакции у локальных файлов и прочую полезную информацию.

В репозитории создана новая редакция, однако в рабочем каталоге «test» еще нет информации об этом обновлении. Необходимо выполнить update в этом каталоге, чтобы получить изменения из репозитория. Выполните команду update из каталога «test»:

› cvs update

cvs update: Updating.

U todo.txt

В процессе выполнения команды система изучила содержимое репозитория и рабочего каталога, и обнаружила, что файл todo.txt в репозитории изменился, поэтому он и был обновлён. Буква «U» перед именем файла является сокращением от Update и означает, что файл был обновлен из репозитория целиком, поскольку локальных изменений в нём не было. Что же произойдёт, если перед выполнением команды update изменить файл в рабочем каталоге «test»? Возникнет ситуация, когда требуется совмещение редакций:

• В репозитории редакция 1.2

• В рабочем каталоге «test» изменённая редакция 1.1

В этом случае CVS сначала получает из репозитория изменения к текущей редакции (1.2) относительно исходной локальной редакции (1.1, так как она выглядит в репозитории). Затем CVS совмещает изменения от 1.1 до 1.2 и от 1.1 до текущей локальной копии файла. В результате этих непростых вычислений получается локальный файл, содержащий локальные изменения уже относительно версии 1.2.

RCS file: d:\temp\rep/test/test.c,v

retrieving revision 1.1

retrieving revision 1.2

Merging differences between 1.1 and 1.2 into test.c

M test.c

Буква «М» перед именем файла указывает, что файл был изменен локально, и операция commit еще не проводилась. Иными словами, в рабочем каталоге присутствуют изменения, которых нет в репозитории.

WINCVS Алгоритм, реализующий данную функциональность, довольно сложен, и описание его выходит за рамки этой статьи. Интересующиеся могут поискать информацию по ключевым словам CVS, RCS, diff3, merge.

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

WINCVS Обновление рабочего каталога происходит по команде Update selection… из меню Modify. Обновляется каталог или выбранные файлы, в зависимости от того, что выделено.

 

Разрешение конфликтов

Конфликт может возникнуть при совмещении двух изменений, если они пересекаются или расположены слишком близко друг к другу. Поскольку совмещение (merge) возникает при изменении текста и в репозитории, и в рабочем каталоге, вы не получите конфликта, если не меняете файлов локально (например, просто скачиваете обновления из общедоступного репозитория в Интернете). Вы также не получите конфликта, если никто кроме вас не производит обновления репозитория, например, при использовании CVS лично для себя в домашних условиях. Если же вы работаете в команде, которая активно развивает исходный текст - рано или поздно конфликт неизбежен.

При возникновении конфликта вывод CVS выглядит аналогично нижеследующему.

cvs update: Updating.

RCS file: d:\temp\rep/test/test.c,v

retrieving revision 1.1

retrieving revision 1.2

Merging differences between 1.1 and 1.2 into test.c

rcsmerge: warning: conflicts during merge

cvs update: conflicts found in test.c

C test.c

Буква C помечает файл, в котором был обнаружен конфликт. При указании ключа -q или -Q сообщений о конфликтах будет меньше, но сути это не меняет.

WINCVS CVS разработан так, чтобы никогда не терять изменений. Поэтому во многих случаях он сохраняет резервные копии в файлах с именами начинающимися с «.#» (точка, решётка). В общем случае имя файла выглядит так: «.#исходное-имя-файла.номер.редакции», например «.#test.c.1.1». Например, эти файлы сохранят измененные версии на случай ошибочного разрешения конфликта.

Внутри файла, в котором обнаружен конфликт, проблемные участки текста будут заключены в своеобразные скобки:

‹‹‹‹‹‹‹

зона конфликта

›››››››

Внутри зоны конфликта также будет находиться разделитель «========», который отделяет ваше изменение от проблемного, полученного из репозитория. Полностью маркировка конфликта выглядит так:

‹‹‹‹‹‹‹

имя-файла локальное (Ваше) изменение

=======

редакция из репозитория

››››››› номер редакции в репозитории

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

ПРЕДУПРЕЖДЕНИЕ CVS считает, что если время модификации файла (modification time) изменилось с момента обнаружения конфликта, то проблема решена и файл готов к отправке в репозиторий. Поэтому сначала рекомендуется просмотреть все конфликты в файле (их может быть несколько) используя, например, поиск строки “‹‹‹”, понять, как они должны быть решены, и уже потом «одним движением» внести все правки. Если же вы исправите не все конфликты и сохраните файл, а затем выполните операцию commit, в репозитории окажется файл с маркировкой конфликта внутри, и проблемы практически неизбежны. CVS сообщит о таких случаях предупреждением «warning: file `имя-файла' seems to still contain conflict indicators», но версию в репозиторий всё же отправит, поскольку не может быть уверен в своих догадках.

Пример конфликта в исходном тексте на C++

void clear_string(char *p) {

 *p=0; // здесь обнаружена ошибка - не было проверки на NULL

}

Ошибку обнаружили двое программистов независимо и, поскольку изменение простейшее, решили тут же её и поправить. Один сделал так:

void clear_string(char *p) {

 if (p) *p=0;

}

А другой так:

void clear_string(char *p) {

 if (!p) return;

 *p=0;

}

Первый поместил версию в репозиторий. Второй попытался тоже обновить репозиторий, на что CVS сообщил, что рабочий каталог устарел и требуется обновление:

cvs commit: Up-to-date check failed for `test.c'

cvs commit: file `todo.txt' had a conflict and has not been modified

Он обновляет свой рабочий каталог командой cvs update и получает сообщение о конфликте. Открыв файл, он обнаруживает следующее:

void clear_string(char *p) {

‹‹‹‹‹‹‹ test.c

 if (!p) return;

 *p=0;

=======

 if (p) *p=0;

››››››› 1.2

}

Разрешение конфликта не займёт много времени, и файл вновь принимает рабочий вид.

void clear_string(char *p) {

 if (p) *p=0;

}

После этого можно выполнить операцию commit

 

Работа с редакциями

Управление редакциями может показаться довольно запутанным процессом, если не разобраться как следует в том, как CVS управляет ими в репозитории. Кратко сформулируем основные правила:

• У каждого файла своя нумерация редакций. Поэтому нет единой нумерованной редакции для всего проекта.

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

• Номера редакций могут только возрастать.

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

Установка символического имени для редакций

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

› cvs tag release-1-0

cvs tag: Tagging.

T readme.txt

T test.c

T todo.txt

В отличие от команд add, remove и модификации файла, команда tag работает напрямую с репозиторием и присваивает метки редакциям файлов, которые находятся в настоящий момент в рабочем каталоге. Поскольку команда модифицирует репозиторий напрямую, она не принимает во внимание локальные изменения, которые Вы, возможно, внесли в файлы в рабочем каталоге. Можно заставить CVS проверить, что все файлы находятся в репозитории, добавив ключ -c к команде tag:

› cvs tag -c release-1-0

cvs tag: test.c is locally modified

cvs [tag aborted]: correct the above errors first!

WINCVS Создать метку позволяет команда Create a tag on selection… из меню Modify.

Получение конкретной редакции файла

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

Такие метки нужно сбрасывать явно, если их действие больше не требуется. Для их сброса используется ключ -A команды update

› cvs update -A

WINCVS В этой оболочке нет специальных команд для выполнения таких операций. Вместо этого используется закладка sticky options в диалоге Update. Чтобы сбросить липкие метки, используйте галочку “Reset any sticky date/tag/-k options” в том же диалоге

Такая команда сбросит все прилипшие метки и получит самую свежую копию из репозитория для всех файлов в текущем каталоге (рекурсивно для подкаталогов). Получить текущее состояние липких меток можно командой status.

> cvs status

cvs status: Examining .

===================================================================

File: readme.txt        Status: Up-to-date

   Working revision:    1.1     Mon Dec  9 13:27:28 2002

   Repository revision: 1.1     d:\temp\rep/test/readme.txt,v

   Sticky Tag:          1.1

   Sticky Date:         (none)

   Sticky Options:      (none)

Теперь рассмотрим команды, которые помогут получить самые различные редакции файлов.

Чтобы получить конкретную редакцию по номеру или метке для отдельного файла, подкаталога или всего проекта, используется ключ -r для команды update, параметром к которому должен быть либо номер редакции, либо ранее присвоенная метка. Следующая команда приведёт рабочий каталог к состоянию, в котором эта метка была присвоена:

› cvs update -r release-1-0

А эта команда достанет из репозитория самую первую редакцию файла readme.txt - то состояние, в котором он был добавлен в репозиторий:

› cvs update -r 1.1 readme.txt

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

ПРЕДУПРЕЖДЕНИЕ Использование номера редакции при обновлении каталога относительно бессмысленно. Редакции файлов независимы, поэтому команда cvs update -r 1.2 достанет из репозитория все файлы, которые вообще хоть раз обновлялись, и именно их вторую редакцию. Скорее всего, это будет несовместная сборка файлов из разных периодов жизни проекта, в том числе и уже удалённых. Пользуйтесь символическими метками (тегами) для установления логической связи между редакциями файлов.

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

› cvs update -D date_spec

Такое обновление также создаёт липкие метки на файлах - пока они их не сброшены, Вы не получите обновлений с датой позже указанной. Формат даты (date_spec) может быть очень разным, CVS поддерживает многое из спецификации ISO8601, но вам, скорее всего, понадобится всего несколько вариантов, которые я здесь приведу в качестве примера:

2002-12-06 // дата в формате YYYY-MM-DD

2002-12-06 18:22 // дата в формате YYYY-MM-DD HH:MM

6 Dec 2002 // дата в формате DD MMM YYYY

yesterday // вчера

1 hour ago // час назад

7 days ago // неделю назад