Алексей Махоткин

домашняя страница

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

Go to the first, previous, next, last section, table of contents.


Ревизии

В большинстве случаев использования CVS не требуется сильно беспокоиться о номерах ревизий; CVS присваивает номера типа 1.1, 1.2 и т. д., и этого достаточно. Некоторые, однако, хотели бы иметь больше информации и лучше контролировать то, как CVS присваивает номера ревизий.

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

Номера ревизий

Каждая ревизия файла имеет уникальный номер ревизии. Номера ревизий выглядят как `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 !
       +—–+    +—–+    +—–+    +—–+    +—–+

Может также оказаться, что в номерах ревизий будет больше одной точки, например, `1.3.2.2’. Такие номера означают ревизии, находящиеся на ветках (see section Создание ветвей и слияние); эти номера подробно описаны в section Ветки и ревизии.

Версии и ревизии

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

Назначение номеров ревизий

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

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

Обычно совершенно не требуется заботиться о номерах ревизий — проще думать о них, как о служебных номерах, за которыми следит CVS, а также о метках, обеспечивающих хороший способ различать, например, версию 1 вашего продукта от версии 2 (see section Метки ревизий). Однако, если вы хотите установить номер ревизии, вам поможет ключ командной строки `-r’ команды cvs commit. Ключ `-r’ подразумевает использование ключа `-f’, в том смысле, что он приводит к фиксированию файлов, даже если он не были изменены.

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

$ cvs commit -r 3.0

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

Метки ревизий

Номера ревизий живут своей собственной жизнью. Они могут совершенно никак не соотноситься с номером версии вашего программного продукта. В зависимости от того, как вы используете CVS, номера ревизий могут измениться несколько раз между двумя выпусками продукта. Например, файлы с исходными текстами RCS 5.6 имеют такие номера ревизий:

ci.c            5.21
co.c            5.9
ident.c         5.3
rcs.c           5.12
rcsbase.h       5.11
rcsdiff.c       5.10
rcsedit.c       5.11
rcsfcmp.c       5.9
rcsgen.c        5.10
rcslex.c        5.11
rcsmap.c        5.2
rcsutil.c       5.10

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

Вы захотите выбрать какое-либо соглашение об именах меток, основываясь, например, на имени программы и номере ее версии. Например, можно взять имя программы, за которым следует номер версии, в котором символ `.’ заменен на `-’, так что CVS 1.9 будет помечен как cvs1-9. Если вы выберете стабильные правила именования, вам не придется постоянно угадывать, называется ли метка cvs-1-9, cvs1_9 или как-то еще. Вы можете даже принудительно задать эти правила именования в файле `taginfo’ (see section Настройка журналирования).

В нижеследующем примере показано, как добавить метку к файлу. Команды должны выполняться внутри вашего рабочего каталога, то есть там, где находится файл `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/tc/backend.c,v
    Sticky Tag:         (none)
    Sticky Date:        (none)
    Sticky Options:     (none)

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

Полный синтаксис команды cvs tag, включая разнообразные ключи командной строки, описан в section Краткий справочник по командам CVS.

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

$ cvs tag rel-1-0 .
cvs tag: Tagging .
T Makefile
T backend.c
T driver.c
T frontend.c
T parser.c

(Если вы дадите CVS каталог в качестве параметра командной строки, она обычно оперирует над всеми файлами в этом каталоге и, рекурсивно, ко всем подкаталогам, которые тот содержит. See section Рекурсивное поведение.)

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

$ cvs checkout -r rel-1-0 tc

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

Вы можете также извлечь модуль по состоянию на любую дату. See section Ключи команды checkout. Задав команде checkout ключ командной строки `-r’, следует остерегаться липких меток; см. section Липкие метки.

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

        file1   file2   file3   file4   file5

        1.1     1.1     1.1     1.1  /–1.1*      <-*-  TAG
        1.2*-   1.2     1.2    -1.2*-
        1.3  - 1.3*-   1.3   / 1.3
        1.4          \  1.4  /  1.4
                      -1.5*-   1.5
                        1.6

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

        file1   file2   file3   file4   file5

                        1.1
                        1.2
                1.1     1.3                       _
        1.1     1.2     1.4     1.1              /
        1.2*—-1.3*—-1.5*—-1.2*—-1.1     (— <— Look here
        1.3             1.6     1.3              \_
        1.4                     1.4
                                1.5

Что пометить в рабочем каталоге

Пример в предыдущей секции демонстрирует один из самых распространенных способов выбрать, какие ревизии пометить, а именно: выполнение команды cvs tag без параметров заставляет CVS выбрать ревизии, которые извлечены в текущем рабочем каталоге. Например, если копия файла `backend.c’ в рабочем каталоге была извлечена из ревизии 1.4, то CVS пометит ревизию 1.4. Заметьте, что метка прилагается непосредственно к ревизии 1.4 в репозитории. Пометка – это не изменение файла, и не какая-либо операция, при которой сначала модифицируется рабочий каталог, а затем команда cvs commit переносит изменения в репозиторий.

Возможно, неожиданным обстоятельством того факта, что cvs tag оперирует с репозиторием, является то, что вы помечаете извлеченные ревизии, которые могут отличаться от файлов, измененных в вашем рабочем каталоге. Если вы хотите избежать ошибочного выполнения этой операции, укажите команде cvs tag ключ командной строки `-c’. Если в рабочем каталоге имеются измененные файлы, CVS завершится с сообщением об ошибке, не пометив ни одного файла:

$ cvs tag -c rel-0-4
cvs tag: backend.c is locally modified
cvs [tag aborted]: correct the above errors first!

Как помечать по дате или ревизии

Команда cvs rtag помечает репозиторий по состоянию на определенную дату и время (может использоваться для пометки последней ревизии). rtag работает прямо с содержимым репозитория (не требуется сначала извлекать рабочий каталог).

Нижеследующие ключи командной строки указывают, по какой дате или номеру ревизии помечать. See section Стандартные ключи командной строки, где приведено полное описание.

-D дата
Помечает самую новую ревизию не позднее даты.
-f
Полезно только вместе с `-D дата или `-r метка. Если не обнаружено соответствующей ревизии, вместо игнорирования файла используется самая новая ревизия.
-r метка
Помечать только файлы, содержащие существующую метку метка.

Команда cvs tag также позволяет выбрать файлы по ревизии или по дате, используя те же ключи командной строки `-D’ и `-f’. Однако, это, скорее всего, вовсе не то, что вам надо, потому что cvs tag выбирает, какие файлы помечать, основываясь на файлах, существующих в рабочем каталоге, а не на файлах, существовавших на заданную дату или в заданной ревизии. Таким образом, обычно лучше использовать cvs rtag. Исключением могут быть случаи типа:

cvs tag -r 1.4 backend.c

Удаление, перемещение и удаление меток

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

Однако же, могут быть случаи, в которых метки используются лишь временно или случайно помечаются неверные ревизии. Таким образом, нужно удалить, переместить или переименовать метку. Предупреждение: команды в этой секции опасны, они навсегда уничтожают информацию об истории и восстановление после ошибок может быть трудным или невозможным. Если вы – администратор CVS, вы можете захотеть ограничить использование этих команд с помощью файла `taginfo’ (see section Настройка журналирования).

Чтобы удалить метку, задайте ключ командной строки `-d’ команде cvs tag или cvs rtag. Например:

cvs rtag -d rel-0-4 tc

удаляет метку rel-0-4 из модуля tc.

Когда мы говорим перемещение метки, мы хотим, чтобы существующее имя указывало на другие ревизии. Например, метка stable может указывать на ревизию 1.4 файла `backend.c’, а мы хотим, чтобы она указывала на ревизию 1.6. Чтобы переместить метку, задайте ключ командной строки `-F’ командам cvs tag или cvs rtag. Например, вышеупомянутая задача может быть решена так:

cvs tag -r 1.6 -F stable backend.c

Когда мы говорим переименовать метку, мы хотим, чтобы другое имя указывало на те же ревизии, что и существующее. Например, мы могли ошибиться в написании имени метки и хотим исправить его, пока остальные не начали его использовать. Чтобы переименовать метку, сначала создайте новую метку, используя ключ командной строки `-r’ команды cvs rtag, затем удалите старое имя. После этого новая метка указывает на точно те же самые файлы, что и старая. Например:

cvs rtag -r old-name-0-4 rel-0-4 tc
cvs rtag -d old-name-0-4 tc

Пометки при добавлении и удалении файлов

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

Однако, при этом можно потерять небольшое количество информации. Например, предположим, что файл был добавлен, а затем удален. Затем, если для этого файла отсутствует метка, нет способа сказать, потому ли это, что метка соответствует времени перед тем, как файл был добавлен, или после того, как он был удален. Если вы выполните cvs rtag с ключом командной строки `-r’, то CVS помечает файлы, которые были удалены, избегая таким образом проблемы. Например, можно указать `-r HEAD’, чтобы пометить головную ревизию.

Команда cvs rtag имеет ключ командной строки `-a’, очищающий метку с удаленных файлов, которые в противном случае не были бы помечены. Например, можно указать этот ключ вместе с `-F’ при перемещении метки. Если переместить метку без `-a’, то метка на удаленных файлах все еще ссылалась бы на старую ревизию и не отражала бы того факта, что файл был удален. Я не считаю, что это обязательно, если указано `-r’, как отмечено выше.

Липкие метки

Иногда ревизия, находящаяся в рабочем каталоге, содержит также дополнительную информацию о себе: например, она может находиться на ветке (see section Создание ветвей и слияние), или же может быть ограничена с помощью `checkout -D’ или `update -D’ версиями, созданными ранее указанной даты. Так как эта информация долговременно сохраняется, то есть действует на последующие команды над рабочей копией, то мы называем ее липкой.

В большинстве случаев липкость – это запутанный аспект CVS, о котором вам не следует думать. Однако, даже если вы не желаете использовать эту возможность, вы все же захотите что-нибудь узнать о липких метках (например, как их избежать!).

Можно использовать команду status, чтобы посмотреть, какие установлены липкие метки или даты:

$ cvs status driver.c
===================================================================
File: driver.c          Status: Up-to-date

    Version:            1.7.2.1 Sat Dec  5 19:35:03 1992
    RCS Version:        1.7.2.1 /u/cvsroot/yoyodyne/tc/driver.c,v
    Sticky Tag:         rel-1-0-patches (branch: 1.7.2)
    Sticky Date:        (none)
    Sticky Options:     (none)

Липкие метки остаются на ваших рабочих файлах до тех пор, пока вы не удалите их с помощью `cvs update -A’. Опция `-A’ извлекает версию файла из головной ревизии ствола и забывает обо всех липких метках, датах и ключах командной строки.

Самое распространенное использование липких меток – указать, над какой ветвью идет работа, что описано в section Доступ к веткам. Однако, липкие метки также используются и без веток. Предположим, например, что вы хотите избежать обновления вашего рабочего каталога, чтобы защититься от изменений, которые делают ваши коллеги. Вы, конечно, можете просто не выполнять команду cvs update. Если же вы хотите избежать обновления только части большого дерева, то липкие метки могут помочь. Если вы извлечете определенную ревизию, скажем, 1.4, то она станет липкой. Последующие команды cvs update не станут извлекать последнюю ревизию до тех пор, пока вы не очистите метку с помощью cvs update -A. Точно так же, использование ключа командной строки `-D’ команд update и checkout задает липкую дату, которая используется для будущих извлечений.

Люди часто хотят извлечь старую версию файла без установки липкой метки. Это можно сделать с помощью ключа командной строки `-p’ команд checkout или update, которая посылает содержимое файла на стандартный вывод. Например:

$ cvs update -p -r 1.1 file1 >file1
===================================================================
Checking out file1
RCS:  /tmp/cvs-sanity/cvsroot/first-dir/Attic/file1,v
VERS: 1.1
***************
$

Однако, это не самый простой способ, если вы спрашиваете, как отменить последнее фиксирование (в этом примере – поместить `file1’ обратно в то состояние, в котором он был в ревизии 1.1). В этом случае лучше будет использовать ключ командной строки `-j’ команды update; дальнейшее обсуждение находится в section Слияние изменений между двумя ревизиями.


Go to the first, previous, next, last section, table of contents.

Comments