phdru.name / Russian / Software / VersionControl

Version Control

Теги и бранчи в CVS и SVN.

В CVS, теги и ветви (branches) представляют собой отдельные специальные сущности. В Subversion это не так. В SVN тегов и бранчей нет вообще, но они имитируются с помощью директорий. Есть директория trunk (хотя она могла бы называться как угодно - это просто традиционное имя), есть директории tags и branches (такие же условные имена). Если надо создать тег или бранч - рабочую директорию (trunk, или любую другую) копируют в поддиректорию в tags или branches; затем делают checkout именно этой поддиректории, и с этой новой рабочей копией работают отдельно.

Тут следует напомнить, что всё, что говориться о файлах и директориях в Subversion - это чистая виртуальщина, эмуляция. Все манипуляции выполняются SVN в своей базе данных. Но выполняются они - с точки зрения пользователя - командами, вполне напоминающими традиционные операции создания и манипулирования файлов и директорий - svn mkdir, svn copy, svn rename, svn move, svn delete.

Операция копирования директорий в Subversion весьма эффективно реализована. Сначала на старую директорию просто ставится ссылка; в дальнейшем при изменении файлов новые файлы копируются, а на старые продолжают оставаться ссылки. Это позволяет создавать теги и бранчи копированием директорий без потери эффективности как по скорости, так и по памяти. В CVS время на обработку тега/бранча растёт по мере роста размера репозитория.

Всякая документация на CVS говорит "почаще ставьте теги - это позволит вам в любой момент вернуться к предыдущему состоянию кода." Про бранчи так не говорится, потому что работа с бранчами в CVS несколько запутана, а переливание патчей из ветви в ветвь бывает болезненным (из-за конфликтов).

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

Приведу подробный пример. Сначала отступление, зачем вообще нужны теги и бранчи. представьте, что вы участвуете в разработке довольно большой и сложной коммерческой программы. Вот вышла версия 1.0 этой программы. Прошёл месяц. За это время разработчики нагородили какого-то нового кода. Тут от пользователя приходит сообщение об ошибке. Как эту ошибку исправить? Дать пользователю новую версию кода из репозитория? Нельзя! Она ещё не вполне стабильна, и там могли произойти несовместимые изменения, например, в формате базы данных.

Тогда делают возврат к версии 1.0. Код в репозитории в момент выпуска версии 1.0 был помечен символическим тегом, например, RELEASE-1.0. Соответственно, состояние репозитория по этому тегу извлекается в новую директорию, там исправляется ошибка, код компилируется, упаковывается и новая программа отправляется заказчику или заказчикам. Патч для исправления ошибки вносится в новый, разрабатываемый код.

Бранч нужен для того, чтобы продолжать работать в ветке программы даже если основная ветвь продолжает развиваться своим путём. Например, если ошибок в версии 1.0 несколько, и исправления этих ошибок хочется внести в репозиторий. Тег в CVS не позволяет закоммитить изменения, а бранч позволяет. Соответственно, при выпуске версии 1.0 репозиторий помечается символьным бранчевым тегом, а при необходимости вернуться эту ветку извлекают из репозитория, и с ней работают. Все коммиты будут попадать в ветку, не в ствол, а если их надо перенести в ствол - для этого в CVS есть команда join.

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

Так вот, в SVN всё это делается достаточно просто. Для того, чтобы создать тег или бранч, ствол (или уже существующий тег или бранч) просто копируются командой svn copy внутри репозитория. Имя новой директории и будет именем тега/бранча. Потом новая директория извлекается (checkout) в рабочую копию, и с ней работают. Теги и бранчи в SVN ничем не отличаются, коммитить изменения можно и в бранч, и в тег. Деление на tags и branches - чисто условное. В действительности каждый коммит в репозитории имеет порядковый номер (номер ревизии), и по этому номеру его и можно использовать.

Для переливания изменений между ветками разработки есть команда svn merge, которая выполняется в рабочей директории, и которой надо указать URL тега/бранча, из которого берутся изменения, и номера ревизий, по отношению к которым эти изменения сравниваются. Например, надо перелить патч, исправляющий ошибку в версии 1.0, в основной ствол. Допустим, ситуация такая: версия 1.0 программы была выпущена на основе ревизии 288 репозитория; ошибка была исправлена в ревизии 455; последний коммит был сделан в ревизии 534. Для переливания патча в основную ветку нужно сравнить (сделать diff) между ревизиями 455 и 288, и произошедшие изменения приложить в рабочей директории. Команда merge будет выглядеть так:

$ svn merge -r288:455 svn://repository/path/to/svn
Изменения наложатся в рабочей директории, после чего можно сделать коммит, и получить ревизию 535. В лог при этом рекомендуется писать номера ревизий, относительно которых делался патч - Subversion пока не имеет средств отслеживать эти номера, и задача их запоминания возлагается на пользователя.


Эта страница http://phdru.name/Russian/Software/VersionControl/tags_branches.html была сгенерирована 08.06.2014 в 20:51:48 из шаблона CheetahTemplate tags_branches.tmpl; Некоторые права зарезервированы. Вы можете узнать о технических аспектах этого сайта.