Использование ветвей и меток в CVS Предположим, вы ведете свой проект, используя CVS в качестве системы контроля версий. Вы выпускаете версию 1.0 своего продукта, она уходит на полки магазинов, а вы полным ходом начинаете разрабатывать версию 2.0. Через небольшое время от недовольных пользователей начинают поступать сообщения об ошибках. Разобравшись, вы выясняете, что для того, чтобы исправить ошибку, требуется внести всего лишь небольшое исправление в исходные тексты версии 1.0. Такая ситуация идеально обрабатывается с помощью таких возможностей CVS, как метки и ветки. Метка -- это имя, которое вы дали определенному набору ревизий файлов, составляющих проект. Обычно метки создаются в ключевых точках развития проекта, таких как выпуск новой версии. Вернемся немного назад по линии времени и в момент выпуска версии номер один пометим те ревизии файлов с исходниками, которые составляют эту версию. $ cvs rtag PRODUCT-1-0 product ``product'' -- это название модуля, в котором хранятся исходные тексты вашего продукта. Теперь начнем разработку 2.0. Помните, что помеченная версия 1.0 доступна нам в любой момент: $ cvs checkout -r PRODUCT-1-0 product Создаст каталог product/, внутри которого будут все файлы, из которых в свое время была скомпилирована версия 1.0. Если выполнить просто команду $ cvs checkout product то в каталоге product/ окажется текущая разрабатываемая версия, находящаяся на полпути между 1.0 и 2.0. Итак, раздаются первые звонки от пользователей с сообщениями об ошибках. В результате разбирательства выясняется, что ошибку можно исправить небольшим исправлением. Создадим ветку, в которой мы будем исправлять ошибку: $ cvs rtag -b -r PRODUCT-1-0 PATCHED-1-0 product (Ключ ``-b'' и означает "создать ветвь"). Теперь сделаем отдельный рабочий каталог, в котором мы будем исправлять ошибки: $ cvs checkout -r PATCHED-1-0 -d product-patched product У вас появился каталог product-patched/ (его имя заданно с помощью ключа -d). В настоящий момент в нем находятся все файлы в том состоянии, в котором они были на момент выпуска версии 1.0. Исправим ошибку. Скомпилируем. Теперь зафиксируем изменение на ветке PATCHED-1-0: $ cvs commit Готово. Дело в том, что когда вы извлекали отдельный рабочий каталог для исправления ошибок, CVS запомнила, что использовалась ветвь PATCHED-1-0, и теперь именно эта ветвь будет использоваться для всех действий в этом рабочем каталоге. Теперь, после того, как версия 1.01 отправлена пользователям, можно удалить каталог product-patched/, потому что исходные тексты этой версии доступны в репозитории с помощью все той же команды $ cvs checkout -r PATCHED-1-0 -d product-patched product В появившемся каталоге product-patched/ будет находиться все та же версия 1.01. Теперь можно внести еще одно исправление, создав версию 1.02 и зафиксировать ее (фиксация автоматически произойдет на ветке), при этом нисколько не мешая разработке версии 2.0, которая происходит на так называемом "основном стволе". Автоматическое слияние изменений с ветви на ствол Итак, теперь дерево ревизий в вашем проекте выглядит так: +-----+ | 1.1 | +-----+ | +-----+ | 1.2 | +-----+ | +-----+ | 1.3 | Эта ревизия помечена как PRODUCT-1-0 и является +-----+ точкой ответвления | |------- исправление#1 | \ исправление#2 +-----+ \ +---------+ +---------+ | 1.4 | --| 1.3.1.1 |---------------| 1.3.1.2 | +-----+ +---------+ +---------+ | | +-----+ | исправление#3 | 1.5 | | +-----+ +---------+ | | 1.3.1.3 | +-----+ +---------+ | 1.6 | +-----+ Ревизии с 1.1 по 1.6 -- это основной ствол (trunk). Ревизии с 1.3.1.1 по 1.3.1.3 -- это ветка, называемая PATCHED-1-0 и имеющая номер 1.3.1 (в номерах веток четное количество точек!). Вы можете посмотреть содержание исправлений, используя команду $ cvs diff -r PRODUCT-1-0 -r PATCHED-1-0 В принципе вы можете записать результат этой команды diff в файл, пойти в каталог, где находится разрабатываемая версия вашего продукта, и скормить этот файл программе `patch'. Скорее всего, изменения будут внесены практически без проблем, максимум, что потребуется -- небольшая ручная правка. Теперь вы можете сказать $ cvs commit и в исходниках новой версии продукта будут зафиксированы требуемые изменения. Тот же самый процесс можно еще больше автоматизировать, не используя при этом ничего, кроме cvs. Зайдите в каталог, содержащий разрабатываемую версию продукта, и скажите $ cvs update -kk -j PRODUCT-1-0 -j PATCHED-1-0 В результате этой операции получится почти то же самое, что и при использовании программы `patch'. Единственная разница -- при обнаружении конфликтов. Предположим, что в старой версии файла src.c была строчка v.push_back(elem); Исправляя продукт, вы заменили его на v.push_back(elem2); а в новой, разрабатываемой версии, из-за смены типа данных эта строчка выглядит как m.insert(elem); В результате выполнения команды `cvs update' в файле src.c образуется конфликт: в нем появятся такие строки: <<<<<<< src.c v.push_back(elem2); ======== m.insert(elem); >>>>>>>> src.c Исходная версия src.c, находившаяся в вашем рабочем каталоге, записана под именем, например, `.#src.c.1.2'. Вам надо разобраться в причине конфликта, оставить только одну из конфликтующих строк, убрать маркеры конфликта (<<<<<<<, ======= и >>>>>>>). Файл `.#src.c.1.2' можно удалить. Теперь, когда конфликты устранены (или их и так не было), можно сказать `cvs commit', и в основной ствол будут внесены все три изменения, которые вы сделали на ветке PATCHED-1-0. В случае использования команды patch она, встретив конфликт между .diff-файлом и файлом src.c, записала бы этот конфликт в src.c.rej, и вам все равно пришлось бы разобраться с ним вручную. Ключ -kk нужен, чтобы избавиться от ложных конфликтов, связанных с подстановкой ключевых слов. В большинстве случаев, как показывает практика, конфликтов или не возникает вовсе, или же они тривиальны и решаются за несколько секунд. Дополнительная информация: http://www.cyclic.com. "Введение в CVS": http://alexm.here.ru/cvs-intro-rus/cvs-intro-rus.html Русский перевод документации на CVS: http://alexm.here.ru/cvs-ru/ Alexey Mahotkin $Date: 2000/04/17 22:19:34 $