CVS -- Система Управления Параллельными Версиями

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

Доступ к репозиторию

Для доступа к репозиторию Web-SynDic нужно поместить в файл .profile или .bashrc такие строки (вместо login укажите свой login на сервере zeta.cs.karelia.ru):

CVSROOT=:pserver:login@zeta.cs.karelia.ru:/usr/local/cvsroot
export CVSROOT

Вам сначала потребуется войти в систему. При входе в систему проверяется ваш пароль. Это происходит при выполнении команды login, которая спрашивает у вас пароль:

cvs login
CVS password: _

После того, как вы ввели пароль, CVS проверяет этот пароль на сервере zeta.cs.karelia.ru. Если результат положителен, то комбинация имени пользователя, машины, пути к репозиторию и пароля сохраняются в специальном файле, чтобы при дальнейшей работе с этим репозиторием от вас не требовалось запускать cvs login. (Если результат проверки отрицателен, CVS пожалуется, что пароль неверен, и, естественно, он не будет сохранен.)

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

Пароль к определенному сетевому репозиторию можно удалить из файла паролей с помощью команды cvs logout.

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

Основные команды CVS

Репозиторий настроен так, что имеется модуль Web-SynDic. Сначала вам надо получить рабочую копию исходного кода. Используйте команду

$ cvs checkout Web-SynDic

при этом будет создан каталог Web-SynDic, в который будут помещены все файлы с исходными текстами.

$ cd Web-SynDic
$ ls
CVS/  doc/  src/

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

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

Результатом нижеприведенной команды будет сохранение в репозиторий новой версии файла с именем filename.

$ cvs commit filename

Тогда как следующая команда сохранит в репозитории все измененные файлы в текущей директории и всех ее поддиректориях.

$ cvs commit

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

Переменная окружения $CVSEDITOR определяет, какой именно редактор будет вызван. Если $CVSEDITOR не установлена, то используется $EDITOR, если она, в свою очередь, установлена. Если обе переменные не установлены, используется редактор по умолчанию для вашей операционной системы, например, vi под UNIX или notepad для Windows 95/NT.

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

Перед тем, как перейти к другим занятиям, вы решаете удалить рабочую копию Web-SynDic. Это можно сделать так:

$ cvs release -d Web-SynDic

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

Добавление файлов и каталогов

Для того, чтобы добавить новый файл в каталог, совершите следующие шаги:

Можно также использовать команду add для добавления нового каталога.

В отличие от большинства других команд, команда add не является рекурсивной.

Работа с двоичными файлами

Ключ командной строки -kb, доступный при использовании некоторых команд CVS, позволяет убедиться, что никаких преобразований, которые CVS производит с текстовыми файлами, не производится. Вот пример создания нового файла с использование флага -kb:
$ cvs add -kb -m "A test file" filename
$ cvs checkout -m "Added binary file" filename
Если файл случайно будет добавлен без -kb, можно использовать команду cvs admin для восстановления. Например,
$ cvs admin -kb filename
$ cvs update -A filename
Команда cvs admin -kb устанавливает метод подстановки ключевых слов по умолчанию для этого файла, но не изменяет рабочую копию файла, которая у вас есть. Однако, используя cvs admin -k для изменения режима подстановки ключевых слов, знайте, что этот режим не подчиняется контролю версий. Это означает, что если, скажем, в старых версиях пакета какой-то файл был текстовым, а затем в новых версиях появился двоичный файл с тем же именем, то CVS не обеспечивает способа извлечь файл в двоичном или текстовом режиме в зависимости от версии пакета, которую вы извлекаете. Для обхода этой проблемы хорошего решения не существует.

Удаление файлов и каталогов

Вот как можно удалить файл, сохранив доступ к его старым ревизиям:

Когда вы фиксируете удаление файла, CVS запоминает, что этого файла более не существует. Впрочем, он может существовать на одних ветках и не существовать на других, или же можно впоследствии добавить другой файл с тем же самым именем. CVS корректно создаст или не станет создавать файл, основываясь на ключах командной строки -r или -D, заданных в командах checkout или update.

Вот пример удаления нескольких файлов:

$ cd test
$ rm *.c
$ cvs remove
cvs remove: Removing .
cvs remove: scheduling a.c for removal
cvs remove: scheduling b.c for removal
cvs remove: use cvs commit to remove these files permanently
$ cvs commit
cvs commit: Examining .
cvs commit: Committing .

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

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

Можно удалить каталог, удалив все файлы в нем. Нет способа удалить сам каталог. Вместо этого вы задаете командам cvs update, cvs checkout или cvs export ключ командной строки -P, который заставит CVS удалять пустые каталоги в рабочем каталоге. Вероятно, лучше всего будет всегда указывать -P, если вы хотите, чтобы существовал пустой каталог, поместите в него пустой файл, например, .keepme, чтобы не дать CVS с ключом -P удалить этот каталог.

Перемещение и переименование файлов

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

$ mv old new
$ cvs remove old
$ cvs add new
$ cvs commit -m "old переименован в new" old new

Это самый простой способ переместить файл, он не подвержен ошибкам, и сохраняет историю совершенных действий. Заметьте, что для доступа к истории файла нужно указать старое или новое имя, в зависимости от периода истории, к которому вы обращаетесь. Например, cvs log old выдаст журнал вплоть до момента переименования.

Когда new фиксируется, нумерация его ревизий начнется с нуля, обычно с 1.1, поэтому если это вам не нравится, используйте ключ командной строки -r номер команды commit.

Просмотр истории

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

Журнальные записи

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

База истории

Вы можете использовать файл history, чтобы журналировать разнообразные действия CVS. Чтобы извлечь информацию из файла history, используйте команду cvs history.

Ревизии и ветви

Ревизии

Каждая ревизия файла имеет уникальный номер ревизии. Номера ревизий выглядят как 1.1, 1.2, 1.3.2.2 или даже 1.3.2.2.4.5. Номер ревизии всегда содержит четное количество десятичных чисел, разделенных точкой. По умолчанию ревизия 1.1 -- первая ревизия файла. В номере каждой следующей ревизии самая правая цифра увеличивается на единицу. Вот пример нескольких ревизий, новые версии находятся правее старых:

       +-----+    +-----+    +-----+    +-----+    +-----+
       ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !
       +-----+    +-----+    +-----+    +-----+    +-----+

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

По умолчанию, CVS назначает номер ревизии, оставляя первую цифру и увеличивая вторую. Например, 1.1, 1.2, 1.3.

При добавлении нового файла вторая цифра всегда будет единицей, а первая цифра будет равняться самой большой первой цифре номера ревизии каждого файла в каталоге. Например, если в каталоге находятся файлы с ревизиями 1.7, 3.1, 4.12, то добавленный файл получит номер ревизии 4.1.

Обычно совершенно не требуется заботиться о номерах ревизий --- проще думать о них, как о служебных номерах, за которыми следит CVS, а также о метках, обеспечивающих хороший способ различать, например, версию 1 вашего продукта от версии 2. Однако, если вы хотите установить номер ревизии, вам поможет ключ командной строки -r команды cvs commit.

Например, для того, что задать всем вашим файлам, включая те, что не изменились, номер ревизии 3.0, выполните команду

$ cvs commit -r 3.0

Заметьте, что номер, который вы указываете вместе с ключом -r, должен быть больше любого существующего номера ревизии. Скажем, если существует ревизия 3.0, вы не можете сказать cvs commit -r 1.3.

Вы можете использовать команду tag, чтобы задать буквенное имя определенной ревизии файла. Вы можете использовать ключ командной строки -v команды status, чтобы увидеть все метки, которые имеет файл, а также какие номера ревизий они представляют. Имена меток должны начинаться с буквы и могут содержать буквы, цифры и знаки - и _. Два имени меток BASE и HEAD зарезервированы для использования в CVS.

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

$ cvs tag rel-0-4 backend.c
T backend.c
$ cvs status -v backend.c
===================================================================
File: backend.c         Status: Up-to-date

    Version:            1.4     Tue Dec  1 14:39:01 1992
    RCS Version:        1.4     /u/cvsroot/yoyodyne/Web-SynDic/backend.c,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

    Existing Tags:
        rel-0-4                     (revision: 1.4)

Команда checkout имеет ключ командной строки -r, позволяющий извлечь определенную ревизию модуля. Этот флаг упрощает извлечение исходного текста, из которого сделана версия 1.0 модуля Web-SynDic в когда-нибудь в будущем.

$ cvs checkout -r rel-1-0 Web-SynDic

Это полезно, например, если кто-то заявляет, что в той версии была ошибка, но вы не можете найти ее в текущей рабочей копии.

Ветви

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

Позже вы можете переместить изменения с одной ветки на другую или же с ветки в ствол, это называется слиянием. Сначала выполняется cvs update -j, чтобы слить изменения в рабочий каталог, а затем эти изменения можно зафиксировать, что фактически приведет к копированию изменений на другую ветку.

Предположим, был выпущен Web-SynDic версии 1.0. Вы продолжаете его разработку, планируя выпустить версию 1.1 через пару месяцев. Через некоторое время ваши пользователи начинают жаловаться на серьезную ошибку. Вы извлекаете версию 1.0 и находите ошибку, для исправления которой требуется всего лишь тривиальное изменение. Однако же, текущая версия исходников находится в крайне нестабильном состоянии и не стабилизируется по крайней мере еще месяц. Вы не можете выпустить исправленную версию, основываясь на свежих исходниках.

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

Вы можете создать ветвь, используя cvs tag -b. Например, если вы находитесь в каталоге с рабочей копией:

$ cvs tag -b rel-1-0-patches

Это отщепляет ветку, основанную на текущей ревизии рабочей копии, и присваивает этой ветке имя rel-1-0-patches.

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

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

$ cvs checkout -r rel-1-0-patches Web-SynDic

Если у вас уже есть рабочая копия, вы можете переключить ее на нужную ветку с помощью update -r:

$ cvs update -r rel-1-0-patches Web-SynDic

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

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

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

Не смущайтесь тем, что номера ветвей для каждого файла различны (1.7.2 и 1.4.2, соответственно). Метка ветви одна и та же, rel-1-0-patches, и все файлы действительно находятся на одной и той же ветке. Номера лишь отражают ту точку в истории файла, в которой появилась ветвь. Из вышеприведенного примера можно узнать, что перед тем, как была создана ветка, driver.c претерпел больше изменений, чем backend.c.

Обычно история ревизий файла -- это линейная возрастающая последовательность номеров:

       +-----+    +-----+    +-----+    +-----+    +-----+
       ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !
       +-----+    +-----+    +-----+    +-----+    +-----+

Однако же, CVS не ограничен линейной разработкой. Дерево ревизий может быть расщеплено на ветви, где каждая ветвь -- самостоятельная линия разработки. Изменения, сделанные на одной ветке, легко могут быть внесены также и в основной ствол.

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

Все ревизии на ветке имеют номера ревизий, образованные путем добавления порядкового номера к номеру ветки. Вот иллюстрация создания веток.

                                                   +-------------+
                           Branch 1.2.2.3.2 ->        ! 1.2.2.3.2.1 !
                                                    / +-------------+
                                                   /
                                                  /
                 +---------+    +---------+    +---------+
Branch 1.2.2 -> _! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !
               / +---------+    +---------+    +---------+
              /
             /
+-----+    +-----+    +-----+    +-----+    +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !  <- The main trunk
+-----+    +-----+    +-----+    +-----+    +-----+
                !
                !
                !   +---------+    +---------+    +---------+
Branch 1.2.4 -> +---! 1.2.4.1 !----! 1.2.4.2 !----! 1.2.4.3 !
                    +---------+    +---------+    +---------+

Обычно не требуется задумываться о точных деталях того, как строятся номера веток, но вот еще подробности: когда CVS создает номер ветки, он берет первое неиспользованное четное число, начиная с двойки. Поэтому, если вы хотите создать ветку от ревизии 6.4, она будет называться 6.4.2. Номера веток, заканчивающиеся на ноль (например, 6.4.0), используются для внутренних нужд CVS. Ветка 1.1.1 имеет специальное значение.

Как с помощью CVS следить за определенными файлами.

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

Команда: cvs watch on [-lR] файлы ...

Команда означает, что разработчикам нужно выполнить команду cvs edit перед редактированием файлов. Для того, чтобы напомнить об этом разработчикам, CVS создаст рабочие копии файлов в режиме только для чтения.

Если среди файлов есть имя каталога, CVS включает слежение за всем файлами, находящимися в соответствующем каталоге репозитория и автоматически включает режим слежения за всеми файлами, которые будут в дальнейшем добавлены в каталог; это позволяет пользователю задать стратегию уведомлений для каждого каталога. Содержимое каталога обрабатывается рекурсивно, если только не задан ключ командной строки -l. Ключ -R позволяет включить рекурсивное поведение, если в файле ~/.cvsrc оно было выключено с помощью ключа -l.

Если список файлов пропущен, по умолчанию обрабатывается текущий каталог.

Команда: cvs watch off [-lR] файлы ...

Команда означает, что при извлечении не нужно создавать файлы в режиме только для чтения; таким образом, разработчики не будут получать напоминания о необходимости использования cvs edit и cvs unedit.

Файлы и ключи командной строки обрабатываются точно так же, как и для cvs watch on.

Как редактировать файлы, за которыми наблюдают?

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

Команда: cvs edit [ключи] файлы ...

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

Команда cvs edit принимает такие же ключи командной строки, что и команда cvs watch add, и устанавливает временное слежение за файлами для пользователя; CVS прекратит слежение, когда будет выполнена команда unedit или команда commit. Если пользователь не хочет получать уведомления, он должен указать ключ -a none.

Файлы и ключи командной строки обрабатываются точно так же, как и для команды cvs watch.

Обычно, когда вы закончите редактирование файлов, используйте команду cvs commit, которая проверит ваши изменения и вернет файлы, за которыми производилось слежение, в обычное состояние только для чтения. Если же вы вместо этого решите отменить изменения, или просто не станете ничего менять, используйте команду cvs unedit.

Command: cvs unedit [-lR] files ...

Отбросить все изменения в рабочих файлах files и привести их в соответствие с ревизией в репозитории. Если кто-либо запросил уведомление об изменениях каких-либо файлов, то CVS делает эти файлы доступными только для чтения. CVS уведомляет пользователей, которые запросили уведомление о команде unedit.

Ключи командной строки и список файлов обрабатываются точно так же, как для команды cvs watch.

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

При использовании сетевого CVS вы можете использовать команды cvs edit и cvs unedit, даже если CVS не смогла успешно соединиться с сервером. Уведомления будут посланы при следующем успешном выполнении какой-либо команды CVS.

Информация о том, кто следит и кто редактирует

Команда: cvs watchers [-lR] files ...

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

Ключи командной строки и список файлов обрабатываются так же, как и в команде cvs watch.

Команда: cvs editors [-lR] files ...

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

Список файлов и ключи командной строки обрабатываются точно так же, как и в команде cvs watch.