К этому моменту вы должны понимать как в хранилище, при каждой фиксации, создается полностью новое дерево файлов (называемое «правка»). Если нет, то вернитесь назад и прочитайте раздел «Правки».
Для этой главы, мы воспользуемся тем же примером, что и
в Глава 1, Фундаментальные понятия. Как вы помните, вы и ваш соразработчик
Салли делите хранилище, содержащее два проекта,
paint
Рё calc
. Как
показывает Рисунок 4.2, «Начальная структура хранилища» каждая
директория проекта содержит поддиректории с названиями
trunk
Рё branches
.
Назначение этих директорий скоро станет понятно.
Как и раньше, будем считать что Салли и вы, оба, имеете
рабочие копии проекта «calc». А конкретно, каждый
из вас имеет рабочую копию /calc/trunk
.
Все файлы относящиеся к проекту находятся в этой поддиректории,
Р° РЅРµ РїСЂСЏРјРѕ РІ /calc
, потому, что ваша команда
решила размещать главную линию разработки в
/calc/trunk
.
Скажем, перед вами была поставлена задача коренной реорганизации
проекта. Рто займет РјРЅРѕРіРѕ времени Рё затронет РІСЃРµ файлы проекта.
Проблема заключается в том, что вы не хотите мешать Салли, которая
прямо сейчас занимается исправлением небольших ошибок. Ее работа
зависит от постоянной доступности последней версии проекта (директории
/calc/trunk
). Если вы начнете пошагово фиксировать
свои изменения, вы конечно же смешаете Салли все карты.
Одним из вариантов является ограничение свободы действий:
вы и Салли перестаете делиться информацией на неделю или две.
В это время начинайте переворачивать и реорганизовывать файлы
рабочей копии, но не фиксируйте и не обновляйте ее пока не
закончите эту задачу. Однако в этом случае появляется несколько
проблем. Во-первых это не очень надежно. Большинство людей
предпочитают часто сохранять свою работу в хранилище, на случай если
вдруг что-то плохое случится с рабочей копией. Во-вторых, это не
достаточно гибко. Если вы работаете на разных компьютерах
(к примеру если рабочая копия /calc/trunk
есть у вас на разных машинах), вам придется вручную копировать
изменения взад и вперед, либо делать всю работу на одном
компьютере. А с другой стороны, вам трудно разделять вносимые
изменения с кем-то еще. Общий при разработке программного обеспечения
«лучший метод организации» это возможность
совместного просмотра проделанной работы по мере продвижения.
Если никто не видит ваших промежуточных фиксаций, вы теряете
потенциальную возможность обратной связи. В конце концов, когда вы
закончите свои изменения, вы можете обнаружить, что очень трудно
заново слить сделанную вами работу с остальным программным кодом
компании. Салли или (кто-то другой) могли внести изменения в
хранилище, которые будет трудно внедрить в вашу рабочую копию
— особенно если вы выполните svn update
после нескольких недель изоляции.
Лучшим решением является создание вашей собственной ветки, или направления разработки, РІ хранилище. Рто позволит вам часто сохранять наполовину поломанную работу РЅРµ пересекаясь СЃ РґСЂСѓРіРёРјРё, Рё РєСЂРѕРјРµ того, РІС‹ можете выборочно разделять информацию СЃ РґСЂСѓРіРёРјРё соразработчиками. Дальше РїРѕ тексту РІС‹ увидите как РІСЃРµ это работает.
Создать ветку очень просто — при помощи команды
svn copy делаете в хранилище копию проекта.
Subversion может копировать не только отдельные файлы но и
директории. Ртак, вам нужно сделать РєРѕРїРёСЋ директории
/calc/trunk
. Где эта новая копия будет
находится? Где угодно — этот вопрос определяется
правилами проекта. Допустим, что правилами вашей команды определено
создание веток в директории /calc/branches
хранилища, и свою ветку вы хотите назвать
my-calc-branch
. Вам необходимо создать новую
директорию /calc/branches/my-calc-branch
которая будет являться копией
/calc/trunk
.
Есть два способа создания копии. Сначала мы покажем
неудачный способ, просто для того, что бы прояснить основные моменты.
Для начала, создается рабочая копия корневой директории проекта
/calc
:
$ svn checkout http://svn.example.com/repos/calc bigwc A bigwc/trunk/ A bigwc/trunk/Makefile A bigwc/trunk/integer.c A bigwc/trunk/button.c A bigwc/branches/ Checked out revision 340.
Теперь создание копии заключается в простой передаче двух путей в пределах рабочей копии команде svn copy:
$ cd bigwc $ svn copy trunk branches/my-calc-branch $ svn status A + branches/my-calc-branch
В этом случае, команда svn copy
рекурсивно копирует рабочую директорию trunk
в новую рабочую директорию
branches/my-calc-branch
. Теперь команда
svn status покажет, что новая директория
запланирована для добавления в хранилище. Обратите внимание
РЅР° знак В«+В» после Р±СѓРєРІС‹ Рђ. Рто означает, что
то что запланировано для добавления является
копией чего-то, а не чем-то новым.
При следующей фиксации, Subversion создаст в хранилище путем
копирования директории /calc/trunk
директорию /calc/branches/my-calc-branch
,
вместо повторного отправления через сеть всей информации
рабочей копии:
$ svn commit -m "Creating a private branch of /calc/trunk." Adding branches/my-calc-branch Committed revision 341.
А теперь, простой способ создания ветки, о котором мы говорили раньше: команда svn copy может оперировать с двумя URL напрямую.
$ svn copy http://svn.example.com/repos/calc/trunk \ http://svn.example.com/repos/calc/branches/my-calc-branch \ -m "Creating a private branch of /calc/trunk." Committed revision 341.
В сущности, между этими двумя методами нет разницы. Оба варианта
создают в правке 341 новую директорию и эта новая директория является
копией /calc/trunk
. Рто показывает Р РёСЃСѓРЅРѕРєВ 4.3, «Хранилище, содержащее РЅРѕРІСѓСЋ РєРѕРїРёСЋВ». Обратите внимание РЅР°
то, что второй метод, кроме прочего, выполняет
немедленную фиксацию. [24]Рта процедура более проста РІ использовании, так как нет
необходимости в создании рабочей копии, отражающей большое хранилище.
Фактически, в этом случае вам вовсе можно не иметь рабочей
РєРѕРїРёРё.
После создания ветки проекта, можно создать новую рабочую копию для начала ее использования:
$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch A my-calc-branch/Makefile A my-calc-branch/integer.c A my-calc-branch/button.c Checked out revision 341.
В этой рабочей копии нет ничего особенного; она является
просто отражением другой директории хранилища. Когда вы
фиксируете изменения, то если Салли сделает обновление, она их
даже не увидит. Ее рабочая копия является копией
/calc/trunk
. (Прочтите далее в этой главе
раздел «Переключение рабочей копии»: команда
svn switch является альтернативным способом
создания рабочей копии ветки.)
Предположим, что прошла неделя и были сделаны следующие фиксации:
Вы внесли изменения в
/calc/branches/my-calc-branch/button.c
,
с созданием правки 342.
Вы внесли изменения в
/calc/branches/my-calc-branch/integer.c
,
с созданием правки 343.
Салли внесла изменения в
/calc/trunk/integer.c
, с созданием
правки 344.
Теперь есть два независимых направления разработки файла
integer.c
, которые показывает Р РёСЃСѓРЅРѕРєВ 4.4, В«Рстория ветвления для РѕРґРЅРѕРіРѕ файла».
Если посмотреть историю сделанных изменений для вашей копии
integer.c
, можно увидеть интересные
вещи:
$ pwd /home/user/my-calc-branch $ svn log --verbose integer.c ------------------------------------------------------------------------ r343 | user | 2002-11-07 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines Changed paths: M /calc/branches/my-calc-branch/integer.c * integer.c: frozzled the wazjub. ------------------------------------------------------------------------ r341 | user | 2002-11-03 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines Changed paths: A /calc/branches/my-calc-branch (from /calc/trunk:340) Creating a private branch of /calc/trunk. ------------------------------------------------------------------------ r303 | sally | 2002-10-29 21:14:35 -0600 (Tue, 29 Oct 2002) | 2 lines Changed paths: M /calc/trunk/integer.c * integer.c: changed a docstring. ------------------------------------------------------------------------ r98 | sally | 2002-02-22 15:35:29 -0600 (Fri, 22 Feb 2002) | 2 lines Changed paths: M /calc/trunk/integer.c * integer.c: adding this file to the project. ------------------------------------------------------------------------
Обратите внимание на то, что Subversion прослеживает
историю ветки integer.c
во времени полностью,
в том числе пересекая точку создания копии. Создание ветки
показывается как событие в истории, потому что файл
integer.c
был неявно скопирован, при
копировании всей директории /calc/trunk/
.
Теперь давайте посмотрим, что будет когда такую же команду Салли
выполнит для своей копии файла:
$ pwd /home/sally/calc $ svn log --verbose integer.c ------------------------------------------------------------------------ r344 | sally | 2002-11-07 15:27:56 -0600 (Thu, 07 Nov 2002) | 2 lines Changed paths: M /calc/trunk/integer.c * integer.c: fix a bunch of spelling errors. ------------------------------------------------------------------------ r303 | sally | 2002-10-29 21:14:35 -0600 (Tue, 29 Oct 2002) | 2 lines Changed paths: M /calc/trunk/integer.c * integer.c: changed a docstring. ------------------------------------------------------------------------ r98 | sally | 2002-02-22 15:35:29 -0600 (Fri, 22 Feb 2002) | 2 lines Changed paths: M /calc/trunk/integer.c * integer.c: adding this file to the project. ------------------------------------------------------------------------
Салли увидит свои собственные изменения правки 344, а ваши сделанные в правке 343 нет. Subversion позаботилась о том, что бы эти две фиксации затронули разные файлы, имеющие разное расположение в хранилище. Тем не менее, Subversion будет показывать то, что два файла имеют одну историю. До создания в правке 341 ветки (или копии) это был один файл. Поэтому и вы и Салли видите изменения сделанные в правке 303 и 98.
Два важных понятия, которые вы должны запомнить из этого раздела.
В отличие от других систем управления версиями, ветки в Subversion существуют в хранилище не в отдельном измерении, а как обычные нормальные директории файловой системы. Такие директории просто содержат дополнительную информацию о своей истории.
Subversion не имеет такого понятия как ветка — есть только копии. При копировании директории результирующая директория становиться «веткой» только потому что вы рассматриваете ее таким образом. Вы можете по-разному думать о директории, по разному ее трактовать, но для Subversion это просто обычная директория которая была создана копированием.
[24] Subversion не поддерживает возможность копирования между хранилищами. При использовании в командах svn copy или svn move URL, можно копировать только элементы из одного и того же хранилища.