Jim Blandy
Для чего нужен CVS?
CVS поддерживает историю дерева каталогов с исходным кодом, работая с последовательностью изменений. CVS маркирует каждое изменение моментом времени, когда оно было сделано, и именем пользователя, совершившим изменение. Обычно человек, совершивший изменение, также предоставляет текстовое описание причины, по которой произошло изменение. Вооружившись всей этой информацией, CVS может отвечать на такие вопросы, как
Кто совершил данное изменение?
Когда они его совершили?
Зачем они это сделали?
Какие еще изменения произошли в то же самое время?
Как использовать CVS -- первый набросок
Перед обсуждением множества разнобразных терминов и идей, давайте взглянем на основные команды CVS.
Настройка вашего репозитория
CVS хранит все изменения в данном проекте в дереве каталогов, называемом "репозиторием" (repository). Перед тем, как начать использовать CVS, вам необходимо настроить переменную среды CVSROOT так, чтобы она указывала на каталог репозитория. Тот, кто ответственен за управление конфигурацией вашего проекта, вероятно, знает, что именно должна содержать в себе эта переменная; возможно даже, что переменная CVSROOT уже установлена глобально.
В любом случае, на нашей системе репозиторий находится в `/usr/src/master'. В этом случае вам следует ввести команды
` setenv CVSROOT /usr/src/master '
если ваш командный интерпретатор -- csh или порожден от него, или
` CVSROOT=/usr/src/master export CVSROOT
если это Bash или какой-либой другой вариант Bourne shell.
Если вы забудете сделать это, CVS пожалуется, если вы попытаетесь запустить его:
$ cvs checkout httpc
cvs checkout: No CVSROOT specified! Please use the `-d' option
cvs [checkout aborted]: or set the CVSROOT environment variable.
$
Извлечение рабочего каталога
CVS не может работать в обычном дереве каталогов; наоборот, вы должны работать в каталоге, который CVS создаст для вас. Точно так же, как вы выписываете книгу из библиотеки перед тем, как забрать ее с собой, вам следует использовать команду `cvs checkout', чтобы получить от CVS рабочее дерево каталогов. Предположим, например, что вы работаете над проектом, называемым `httpc', тривиальным HTTP клиентом:
$ cd
$ cvs checkout httpc
U httpc/.cvsignore
U httpc/Makefile
U httpc/httpc.c
U httpc/poll-server
$
Команда `cvs checkout httpc' означает "Извлечь дерево исходных текстов с именем `httpc' из репозитория, указанного в переменной окружения `CVSROOT'."
CVS помещает дерево в подкаталог `httpc':
$ cd httpc
$ ls -l
total 8
drwxr-xr-x 2 jimb 512 Oct 31 11:04 CVS
-rw-r--r-- 1 jimb 89 Oct 31 10:42 Makefile
-rw-r--r-- 1 jimb 4432 Oct 31 10:45 httpc.c
-rwxr-xr-x 1 jimb 460 Oct 30 10:21 poll-server
Большинство этих файлов -- рабочие копии исходных текстов `httpc'. Однако, подкаталог с именем `CVS' (самый первый) имеет другое назначение. CVS использует его для хранения дополнительной информации о каждом файле в этом каталоге, чтобы определять, какие изменения вы внесли в них с тех пор, как извлекли их из репозитория.
Редактирование файлов
После того, как CVS создал рабочее дерево каталогов, вы можете обычным образом редактировать, компилировать и проверять находящиеся в нем файлы -- это просто файлы.
Например, предположим, что мы хотим скомпилировать проект, который мы только что извлекли:
$ make
gcc -g -Wall -lnsl -lsocket httpc.c -o httpc
httpc.c: In function `tcp_connection':
httpc.c:48: warning: passing arg 2 of `connect' from incompatible
pointer type
$
Кажется, `httpc.c' еще не был перенесен на эту операционную систему. Нам нужно сделать приведение типов для одного из аргументов функции connect. Чтобы сделать это, надо изменить строку 48, заменив
if (connect (sock, &name, sizeof (name)) >= 0)
на
if (connect (sock, (struct sockaddr *) &name, sizeof (name)) >= 0)
$ make gcc -g -Wall -lnsl -lsocket
httpc.c -o httpc $ httpc GET http://www.cyclic.com
...здесь находится текст HTML с домашней страницы Cyclic Software ...
$
Объединение изменений
Так как каждый разработчик использует свой собственный рабочий каталог, изменения, которые вы делаете в своем каталоги, не становятся автоматически видимыми всем остальным в вашей команде. CVS не публикует изменений, пока они не закончены. Когда вы протестируете изменения, вы должны "зафиксировать" (commit) их в репозитории и сделать их доступными остальным. Мы опишем команду cvs commit далее.
Однако, что если другой разработчик изменил тот же файл, что и вы, и, может быть, даже изменил те же самые строки? Чьи изменения будет использованы? Обычно ответить на этот вопрос автоматически невозможно, и CVS совершенно точно некомпетентен, чтобы принимать такие решения. Поэтому перед тем, как фиксировать ваши изменения, CVS требует, чтобы исходные тексты были синхронизированы со всеми изменениями, которые сделали остальные члены группы. Команда cvs update позаботится об этом:
$ cvs update
cvs update: Updating .
U Makefile
RCS file: /u/src/master/httpc/httpc.c,v
retrieving revision 1.6
retrieving revision 1.7
Merging differences between 1.6 and 1.7 into httpc.c
M httpc.c
$
Рассмотрим пример строка за строкой:
`U Makefile'
Строка вида `U файл' означает, что файл просто был обновлен;
кто-то еще внес в этот файл изменения, и CVS скопировал измененный файл в ваш рабочий каталог.
`RCS file:...
retrieving revision 1.6
retrieving revision 1.7
Merging differences between 1.6 and 1.7 into httpc.c'
Это сообщение означает, что кто-то еще изменил `httpc.c'; CVS объединила их изменения с вашими и не обнаружила текстуальных конфликтов. Цифры `1.6' и `1.7' -- это номера редакции (revision numbers), используемые для обозначения определенных точек истории файла. Заметьте, что CVS объединяет изменения только в вашей рабочей копии; репозиторий и рабочие каталоги других разработчиков остаются нетронутыми. От вас требуется протестировать объединенный текст и убедиться, что он верен.
`M httpc.c'
Строка вида `M файл' означает, что файл был модифицирован вами и содержит изменения, которые еще не стали видны другим разработчикам. Это -- изменения, которые вам следует зафиксировать.
Так как CVS объединила чьи-то еще изменения с вашими исходными текстами, следует убедиться, что они все еще работают:
$ make
gcc -g -Wall -lnsl -lsocket httpc.c -o httpc
$ httpc GET http://www.cyclic.com
...HTML text for Cyclic Software's home page follows...
$
Фиксирование изменений
Теперь, когда вы синхронизировали свои исходники с коллегами и протестировали их, вы готовы поместить свои изменения в репозиторий и сделать их видимыми остальным разработчикам. Единственный файл, который вы изменили -- это `httpc.c', но в любом случае можно без опаски запустить cvs update, чтобы получить от CVS список модифицированных файлов:
$ cvs update
cvs update: Updating .
M httpc.c
$
Как и ожидалось, единственный файл, который упоминает CVS -- это `httpc.c'; CVS говорит, что этот файл содержит изменения, которые еще не были зафиксированы. Вы можете зафиксировать их так:
$cvs commit httpc.c
В этом месте CVS запустит ваш любимый текстовый редактори попросит вас ввести описание изменений. После того, как вы выйдете из редактора, CVS зафиксирует ваши изменения:
Checking in httpc.c;
/u/src/master/httpc/httpc.c,v <-- httpc.c
new revision: 1.8; previous revision: 1.7
$
Заметьте, что теперь вы зафиксировали ваши изменения и они видны всем остальным членам группы. Когда другой разработчик исполняет cvs update, CVS внесет ваши изменения в файлы в его рабочем каталоге.
Отслеживание изменений
Теперь вы, возможно, захотите узнать, какие именно изменения внес другой разработчик в файл `httpc.c'. Чтобы увидеть журнальные записи для данного файла, можно использовать команду cvs log:
$ cvs log httpc.c
RCS file: /usr/src/master/httpc/httpc.c,v
Working file: httpc.c
head: 1.8
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 8; selected revisions: 8
description:
The one and only source file for trivial HTTP client
----------------------------
revision 1.8
date: 1996/10/31 20:11:14; author: jimb; state: Exp; lines: +1 -1
(tcp_connection): Cast address stucture when calling connect.
----------------------------
revision 1.7
date: 1996/10/31 19:18:45; author: fred; state: Exp; lines: +6 -2
(match_header): Make this test case-insensitive.
----------------------------
revision 1.6
date: 1996/10/31 19:15:23; author: jimb; state: Exp; lines: +2 -6
...
$
Большую часть текста здесь вы можете игнорировать; следует только обратить внимание на серию журнальных записей после первой строки черточек. Журнальные записи выводятся на экран в обратном хронологическом порядке, исходя из предположения, что недавние изменения обычно более интересны. Каждая запись описывает одно изменение в файле, и может быть разобрано на составные части так:
`revision 1.8'
Каждая версия файла имеет уникальный "номер редакции". Номера ревизии выглядят как `1.1', `1.2', `1.3.2.2' или даже `1.3.2.2.4.5'. По умолчанию номер
1.1 -- это первая редакция файла. Каждое следующее редактирование увеличивает
последнюю цифру на единицу.
`date: 1996/10/31 20:11:14; author: jimb; ...'
В этой строке находится дата изменения и имя пользователя, зафиксировавшего
это изменение; остаток строки не очень интересен.
`(tcp_connection: Cast...'
Это, очевидно, описание изменения.
Команда cvs log может выбирать журнальные записи по дате или по номеру редакции; за описанием деталей обращайтесь к руководству.
Если вы хотите взглянуть на соответствующее изменение, то можете использовать команду cvs diff. Например, если вы хотите увидеть, какие изменения Фред зафиксировал в качестве редакции 1.7, используйте такую команду:
$ cvs diff -c -r 1.6 -r 1.7 httpc.c
Перед рассмотрением того, что нам выдала эта команда, опишем, что означает каждая ее часть.
Вот что выдаст эта команда: