3. Работа с CVS
Пред. |  | След.

## 3. Работа с CVS

Подразумевается, что вы уже имеете опыт базовой работы с CVS.

Администраторы Главного CVS Репозитория `<cvsadm@FreeBSD.org>` являются «владельцами» репозитория CVS и ответственны за все прямые его изменения (в целях чистки или исправления каких-либо вопиющих ошибок коммиттеров при работе с CVS). Если в результате ваших действий с частью репозитория произошел несчастный случай, например, после неверной операции `cvs import` или `cvs tag`, пошлите письмо соответствующей подгруппе Администраторы Главного CVS Репозитория `<cvsadm@FreeBSD.org>` (см. следующую таблицу) и сообщите о проблеме. В наиболее серьезных случаях, касающихся не только какой-либо части репозитория, а дерева CVS в целом, вы можете написать Администраторы Главного CVS Репозитория `<cvsadm@FreeBSD.org>`. Пожалуйста, не надо писать группе Администраторы Главного CVS Репозитория `<cvsadm@FreeBSD.org>` по поводу репозиторного копирования и прочих вопросов, которые может решить соответствующая подгруппа.

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

### Примечание:

Адреса, на которые следует посылать запросы, зависят от области репозитория, которую требуется поправить:

- ncvs@ - репозиторий `/home/ncvs`, основные исходные тексты

- pcvs@ - репозиторий `/home/pcvs`, порты

- dcvs@ - репозиторий `/home/dcvs`, документация

- projcvs@ - репозиторий `/home/projcvs`, прочие проекты

Дерево CVS в настоящее время разделено на четыре независимых репозитория: `doc`, `ports`, `projects` и `src`. Для удобства работы пользователей при распространении через CVSup различные деревья комбинируются в одно, с одним служебным каталогом `CVSROOT`.

### Примечание:

Обратите внимание, что модуль `www`, содержащий исходные тексты веб-сайта FreeBSD, расположен в репозитории `doc`.

В настоящее время, все репозитории CVS располагаются на одной машине, `ncvs.FreeBSD.org`, однако, для обеспечения возможности в будущем разнести их по физически различным машинам, для каждой поддерживается отдельное имя хоста. Их и следует использовать коммиттерам. Наконец, каждый репозиторий расположен в отдельном каталоге. В итоге, общая картина выглядит так:

Таблица 1. Репозитории CVS FreeBSD, хосты и каталоги

Репозиторий | Хост | Каталог
--- | --- | ---
doc | dcvs.FreeBSD.org | /home/dcvs
ports | pcvs.FreeBSD.org | /home/pcvs
projects | projcvs.FreeBSD.org | /home/projcvs
src | ncvs.FreeBSD.org | /home/ncvs

Операции с CVS производятся удаленно, путем установки переменной окружения `CVSROOT` (она должна указывать на соответствующий хост и каталог верхнего уровня, например `ncvs.FreeBSD.org``:``/home/ncvs`) и последующего выполнения команд выгрузки и коммита. Многие коммиттеры определяют команды-синонимы, разворачивающиеся в запуск cvs с правильными параметрами. В частности, пользователи оболочки tcsh(1) могут добавить следующие строки в свой скрипт начальной загрузки `.cshrc`:

alias dcvs cvs -d `user`@dcvs.FreeBSD.org:/home/dcvs alias pcvs cvs -d `user`@pcvs.FreeBSD.org:/home/pcvs alias projcvs cvs -d `user`@projcvs.FreeBSD.org:/home/projcvs alias scvs cvs -d `user`@ncvs.FreeBSD.org:/home/ncvs

Теперь все операции с CVS могут выполняться на локальной машине, а для внесения изменений в официальное дерево CVS следует использовать команду ``X`cvs commit`. Если вам нужно добавить в проект что-либо совершенно новое (например, исходные тексты сторонних разработчиков), нужно использовать команду `cvs import`; обратитесь к странице справочника по cvs(1) за подробностями.

### Примечание:

Пожалуйста, не используйте команды `cvs checkout` или `cvs update` для синхронизации ваших исходных текстов. Протокол CVS не оптимизирован для удаленной работы и требует значительных накладных расходов со стороны сервера. Пожалуйста, используйте метод синхронизации посредством `cvsup`, а основной хост используйте только для собственно коммитов. Наша распределенная сеть серверов cvsup достаточно развита. При необходимости синхронизации с самыми свежими изменениями вы можете пользоваться машиной `cvsup-master`, которая обладает достаточными ресурсами для удаленной работы с CVS; за нее отвечает Jun Kuriyama `<kuriyama@FreeBSD.org>`.

Если вам нужно использовать команды CVS `add` и `delete`, так чтобы в реальности переместить часть исходных текстов подобно действию команды mv(1), нужно запросить операцию «репозиторного копирования» (repository copy). При этом кто-либо из CVS-мастеров скопирует необходимые файлы внутри репозитория на нужное место и даст вам знать об этом. Репозиторное копирование производится для сохранения истории (журналов изменения). Возможность отследить историю изменений очень ценна для всего проекта FreeBSD.

Документация по CVS, учебные материалы и FAQ можно найти по адресу: http://www.cvshome.org/docs/. Очень полезна также книга Карла Фогеля (Karl Fogel) Open Source Development with CVS. Некоторая полезная информация о CVS на русском языке может быть найдена здесь.

Dag-Erling Smørgrav `<des@FreeBSD.org>` написал такой «мини-пример» работы с CVS:

1. Извлечение нужного модуля из репозитория: команда `co` или `checkout`.

   `%` `cvs checkout shazam`

   Эта команда извлечет копию модуля `shazam`. Если модуль с таким именем не существует (не описан в файле modules), будет произведена попытка извлечь директорию верхнего уровня `shazam`.

   Таблица 2. Полезные опции команды `cvs checkout`

   `-P` | Не создавать (точнее, удалить после завершения выполнения) пустые каталоги
   `-l` | Извлекать один уровень каталогов (без подкаталогов)
   `-r`rev`` | Извлечь ревизию, ветвь или тег `rev` для указанного модуля
   `-D`date`` | Извлечь состояние модуля в репозитории на момент `date`

   Примеры в применении к FreeBSD:

   - Извлечь модуль `miscfs`, расположенный в каталоге репозитория `src/sys/miscfs`:

     `%` `cvs co miscfs`

     После выполнения вы получите каталог `miscfs`, содержащий подкаталоги `CVS`, `deadfs`, `devfs` и т.д. Один из них (`linprocfs`) будет пустым.

   - Извлечь те же файлы, но с полным путем:

     `%` `cvs co src/sys/miscfs`

     Теперь у вас есть каталог `src`, содержащий подкаталоги `CVS` и `sys`. Каталог `src/sys` содержит подкаталоги `CVS` и `miscfs` и т.д.

   - Извлечь те же файлы, удалив при этом пустые подкаталоги:

     `%` `cvs co -P miscfs`

     Вы получите каталог `miscfs` с подкаталогами `CVS`, `deadfs`, `devfs`... однако без подкаталога `linprocfs`, поскольку он не содержит файлов.

   - Извлечь каталог `miscfs` без подкаталогов:

     `%` `cvs co -l miscfs`

     Теперь в каталоге `miscfs` будет только один подкаталог `CVS`.

   - Извлечь модуль `miscfs` из ветви 6.X:

     `%` `cvs co -rRELENG_6 miscfs`

     Теперь вы можете изменить исходные тексты и произвести коммит в эту ветвь.

   - Извлечь модуль `miscfs` по состоянию на момент выхода 6.0-RELEASE:

     `%` `cvs co -rRELENG_6_0_0_RELEASE miscfs`

     В этом случае вы не сможете внести изменения в репозиторий, поскольку `RELENG_6_0_0_RELEASE` описывает момент времени, а не ветвь разработки.

   - Извлечь модуль `miscfs` по состоянию на 15 января 2000 г:

     `%` `cvs co -D'01/15/2000' miscfs`

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

   - Извлечь модуль `miscfs`, каким он был неделю назад:

     `%` `cvs co -D'last week' miscfs`

     И вновь, изменения не могут быть записаны.

   Обратите внимание, что мета-данные хранятся в подкаталогах `CVS`.

   Аргументы опций `-D` and `-r` сохраняются (являются «клейкими», sticky), например, при последующем использовании команды `cvs update`.

2. Проверка состояния извлеченных файлов: команда `status`.

   `%` `cvs status shazam`

   Эта команда покажет статус файла `shazam` или каждого файла в директории `shazam`. Для каждого из файлов статус может быть одним из:

   Up-to-date | Файл соответствует репозиторию и не модифицировался
   Needs Patch | Файл не изменялся, но репозиторий содержит обновленную версию
   Locally Modified | Файл соответствует репозиторию, но был изменен локально
   Needs Merge | Файл изменен локально; вместе с тем, файл изменен и в репозитории
   File had conflicts on merge | После последнего обновления возникли конфликты, и они все еще не устранены

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

3. Обновление извлеченного модуля: команда `update`.

   `%` `cvs update shazam`

   Эта команда обновит состояние файла `shazam` или файлов в каталоге `shazam` до наиболее свежих версий выбранной вами при извлечении ветви. Если выбирался «момент времени», не произойдет ничего, если только за истекшее время в репозитории не был перемещен тег или не произошло чего-нибудь еще непредвиденного.

   Полезные опции в дополнение к уже описанным для команды `checkout`:

   `-d` | Извлечь вновь появившиеся или пропущенные ранее подкаталоги
   `-A` | Обновиться до текущего состояния головной ветви
   `-j`rev`` | магическая опция (см. ниже)

   Если вы извлекали модуль с опциями `-r` или `-D`, выполнение команды `cvs update` с другими параметрами `-r` или `-D` или с опцией `-A` приведет к выбору новой ветви, ревизии или даты. Использование опции `-A` удаляет использованные ранее клейкие свойства; опции `-r` и `-D`, наоборот, фиксируют их.

   Теоретически использование `HEAD` в качестве аргумента опции `-r` должно дать тот же результат, что и указание опции `-A`, однако это верно лишь в теории.

   Опция `-d` полезна, если:

   - после извлечения вами модуля кем-либо еще в него были добавлены дополнительные каталоги;

   - вы извлекали верхний уровень модуля при помощи опции `-l`, а в дальнейшем решили извлечь и подкаталоги;

   - вы удалили какие-либо подкаталоги и теперь хотите вновь извлечь их.

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

   `U` | Файл был успешно обновлен.
   `P` | Файл был успешно обновлен (произведен успешный патч из удаленного репозитория).
   `M` | Файл был изменен, и при этом обновлен успешно.
   `C` | Файл был изменен, и при объединении изменений возникли конфликты.

   Объединение (merging) производится, если вы выгрузили рабочую копию какого-то модуля, изменили его, затем кто-либо еще произвел коммит собственных изменений, и, наконец, вы выполняете команду `cvs update`. CVS знает, что производились локальные изменения, и пытается объединить ваши изменения с теми, что произошли в репозитории (от состоянии версии, которую вы выгружали, до версии, до которой вы пытаетесь обновиться). Если изменения происходили с различными частями файла, объединение почти всегда произойдет успешно (хотя результат при этом может не быть синтаксически или семантически корректным).

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

   Если в результате вы видите букву `C`, ваши изменения конфликтуют с изменениями, внесенными в репозиторий (изменения были в одних и тех же или рядом расположенных строках, либо вы изменили файл настолько, что при сравнении `cvs` не смогла удержать контекст и приложить изменения из репозитория). Вам необходимо устранить конфликты, вручную редактируя файл. Конфликтующие фрагменты помечаются строками из знаков `<`, `=` и `>`. В начале каждого из конфликтов присутствует строка из семи знаков `<` и имени файла, затем идет фрагмент, содержащий внесенные вами изменения, разделитель из семи знаков `=`, соответствующий фрагмент из версии файла, содержащейся в репозитории, и, наконец, строка из семи знаков `>` совместно с номером версии, до которой вы обновляли файл.

   Опция `-j` содержит некоторое количество черной магии. При ее наличии локальный файл обновляется до указанной версии так же, как и при использовании опции `-r`, но отслеживаемые номер версии или ветвь не изменяются. Эта опция умеет смысл лишь при парном использовании: при этом делается попытка применить изменения между двумя указанными версиями к локальной копии файла.

   К примеру, вы внесли изменения и произвели коммит в файл `shazam/shazam.c` в FreeBSD-CURRENT, а позднее хотите перенести обновления в FreeBSD-STABLE (Merge-From-Current, MFC). Версия, которая требует переноса — 1.15:

   - Извлеките текущую версию модуля `shazam` для ветви FreeBSD-STABLE:

     `%` `cvs co -rRELENG_6 shazam`

   - Приложите изменения между версиями 1.14 и 1.15:

     `%` `cvs update -j1.14 -j1.15 shazam/shazam.c`

   Почти наверняка вы получите конфликт в строках, содержащих идентификатор файла (`$Id: article.xml,v 1.19 2007-05-09 06:08:50 bvs Exp $` или, в случае FreeBSD, `$FreeBSD$`). Вам потребуется отредактировать файл для устранения конфликта (в данном случае достаточно убрать строки-разделители и вторую строку `$Id: article.xml,v 1.19 2007-05-09 06:08:50 bvs Exp $`, оставив лишь строку с `$Id: article.xml,v 1.19 2007-05-09 06:08:50 bvs Exp $` для FreeBSD-STABLE).

4. Просмотр изменение между локальной версией и версией из репозитория: команда `diff`.

   `%` `cvs diff shazam`

   Эта команда покажет все отличия локального состояния файла (или файлов модуля) `shazam` от состояния, сохраненного в репозитории.

   Таблица 3. Полезные опции команды `cvs diff`

   `-u` | Использовать унифицированный (unified) формат.
   `-c` | Использовать контекстный (context) формат.
   `-N` | Показывать отсутствующие или созданные файлы.

   Всегда имеет смысл пользоваться опцией `-u`, поскольку унифицированный формат гораздо удобнее и лучше читаем, чем почти все другие (в некоторых случаях контекстный формат, генерируемый опцией `-c` может быть несколько лучше, но он гораздо более громоздок). Унифицированный формат различий состоит из серии фрагментов, каждый из которых начинается со строки, состоящей из двух символов `@` и номеров строк, описывающих положение изменившегося участка. Затем следует группа строк: те, что начинаются с пробела, описывают контекст, начинающиеся с символа `-` определяют удаленные строки, наконец, начинающиеся с символа `+` — добавленные.

   Вы можете сравнивать текущее состояние с версией, отличающейся от той, с которой вы извлекали файл, указав опцию `-r` или `-D` подобно командам `checkout` и `update`, или даже получить список изменений между любыми двумя версиями (вне зависимости от того, что лежит в вашей локальной копии), указав две версии при помощи опций `-r` или `-D`.

5. Просмотр журнала изменений: команда `log`.

   `%` `cvs log shazam`

   Если `shazam` является обычным файлом, эта команда выдаст на экран заголовок с информацией о файле, в частности, его местоположении в репозитории, какая версия соответствует текущему состоянию (`HEAD`), в каких ветвях разработки файл присутствует, а также перечислит теги, которыми он помечен. Затем, для каждой версии файла выводится соответствующее ей журнальное сообщение, включающее дату, время и автора коммита, количество добавленных и удаленных строк и собственно журнального сообщения, написанного коммиттером.

   Если `shazam` является каталогом, вышеописанная процедура выполняется для каждого файла в каталоге. Если при этом команде `log` не был указан флаг `-l`, процедура рекурсивно повторяется для всех подкаталогов.

   Команда `log` используется для просмотра истории одного или нескольких файлов в том виде, как она сохранена в репозитории CVS. Используя опцию `-r`rev``, вы можете посмотреть журнальное сообщение к одной определенной версии:

   `%` `cvs log -r1.2 shazam`

   Эта команда покажет журнальное сообщение для версии `1.2` файла `shazam` (или для версий `1.2` каждого из файлов в каталоге `shazam`).

6. Кто что делал: команда `annotate`. Эта команда показывает перед каждой строкой указанного файла (файлов) имя пользователя, вносившего последние изменения в эту строку.

   `%` `cvs annotate shazam`

7. Добавление новых файлов: команда `add`.

   Создайте файл, выполните для него команду `cvs add`, затем произведите запись в репозиторий (коммит): `cvs commit`.

   Точно так же, новые каталоги добавляются в репозиторий путем создания и последующего выполнения команды `cvs add`. Заметьте, что выполнять коммит после добавления каталога не надо.

8. Удаление устаревших файлов: команда `remove`.

   Удалите файл, затем выполните команду `cvs rm` с его именем в качестве параметра, наконец, выполните для него `cvs commit`.

9. Внесение изменений в репозиторий: команда `commit` или `checkin`.

   Таблица 4. Useful `cvs commit` options

   `-f` | Форсировать внесение изменений для не модифицированного файла.
   `-m`msg`` | Указать сообщение для журнала в командной строке (не запускать текстовый редактор).

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

   Хорошие журнальные сообщения очень важны. Они дают возможность другим узнать, зачем вы производили изменения, причем не только в момент их произведения, но и месяцы или годы спустя, когда кто-либо заинтересуется, почему выглядящий нелогично или неэффективно фрагмент кода попал в каши исходные тексты. Кроме того, это очень помогает в оценке того, нужно ли переносить соответствующий код в FreeBSD-STABLE (MFC).

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

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

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

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

   Избегайте коммита большой группы файлов за один раз с одним общим и невнятным сообщением. Напротив, вносите изменения в отдельные файлы (или небольшие группы связанных файлов) с адекватными сообщениями для журналирования.

   Перед коммитом, обязательно:

   - проверьте, что вы будете выполнять коммит в правильную ветвь, посредством команды `cvs status`.

   - проверьте ваши изменения при помощи команды `cvs diff`

   Кроме того, ВСЕГДА указывайте, в какие именно файлы вы вносите изменения, так чтобы не включить в этот список лишних файлов. Команда `cvs commit` без аргументов включит все измененные файлы в текущем каталоге и всех подкаталогах.

Еще несколько полезных советов:

1. Часто используемые опции можно занести в файл `~/.cvsrc`, например:

   cvs -z3 diff -Nu update -Pd checkout -P

   Для данного случая:

   - всегда использовать компрессию уровня 3 для связи с удаленным сервером CVS. В случае медленного соединения это избавит вас от лишней головной боли.

   - всегда использовать опции `-N` (показывать добавленные или удаленные файлы) и `-u` (унифицированный формат) для diff(1).

   - всегда использовать опции `-P` (удалять пустые каталоги) и `-d` (добавлять новые каталоги) при обновлении.

   - всегда использовать опцию `-P` (удалять пустые каталоги) при извлечении файлов и модулей.

2. Пользуйтесь скриптом Эйвинда Эклунда (Eivind Eklund) `cdiff` для просмотра изменению унифицированного формата. Он является оберткой для less(1), добавляющей цветовые коды ANSI для выделения заголовком, добавленных и удаленных строк; прочие строки не модифицируются. Помимо этого, скрипт корректно разворачивает табуляции (которые часто выглядят неправильно в изменениях из-за дополнительного символа в начале строки).

   `textproc/cdiff`

   Просто используйте его вместо more(1) или less(1):

   `%` `cvs diff -Nu shazam | cdiff`

   Помимо этого, некоторые текстовые редакторы, такие как vim(1) (`editors/vim`) поддерживают цветовую синтаксическую разметку многих типов файлов, в том числе файлов изменений и журналов CVS/RCS.

   `%` `echo "syn on" >> ~/.vimrc` `%` `cvs diff -Nu shazam | vim -` `%` `cvs log shazam | vim -`

3. CVS — старая, загадочная и порой слабо предсказуемая в своем поведении программа. Ни один человек не способен удержать в голове все тонкости ее работы, так что не бойтесь спрашивать совета у Искусственного Интеллекта (а именно Администраторы Главного CVS Репозитория `<cvsadm@FreeBSD.org>`).

4. Не оставляйте компьютер в процессе работы команды `cvs commit` (в редакторе при написании журнального сообщения) слишком надолго (более чем на 2–3 минуты). Эта команда блокирует каталог репозитория, в котором она запущена, и не позволяет другим разработчикам изменять его содержимое. Если вам нужно написать длинное журнальное сообщение, подготовьте его заранее и вставьте в редакторе во время выполнения команды `cvs commit`, либо запишите его в файл и используйте опцию CVS `-F`:

   `%` `vi logmsg` `%` `cvs ci -F logmsg shazam`

   Это самый быстрый способ передать журнальное сообщение CVS; однако, вы должны быть внимательны при редактировании файла `logmsg`, поскольку при выполнении коммита у вас не будет шансов его поправить.

5. Вы можете существенно ускорить скорость работы CVS с центральным репозиторием, используя постоянное соединение с репозиторием. Для этого добавьте в файл `~/.ssh/config` строки

   Host ncvs.FreeBSD.org ControlPath /home/`user`/.ssh/cvs.cpath Host dcvs.FreeBSD.org ControlPath /home/`user`/.ssh/cvs.cpath Host projcvs.FreeBSD.org ControlPath /home/`user`/.ssh/cvs.cpath Host pcvs.FreeBSD.org ControlPath /home/`user`/.ssh/cvs.cpath

   Затем откройте постоянное соединение с машиной repoman:

   `%` `ssh -fNM ncvs.FreeBSD.org`

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

Пред. |  | След.
2. Типы коммит битов | Начало | 4. Соглашения и традиции

Этот, и другие документы, могут быть скачаны с http://ftp.FreeBSD.org/pub/FreeBSD/doc/.

По вопросам, связанным с FreeBSD, прочитайте документацию прежде чем писать в <questions@FreeBSD.org>.
По вопросам, связанным с этой документацией, пишите в рассылку <doc@FreeBSD.org>.