http://wiki.linuxformat.ru/wiki/index.php?title=LXF71:Subversion&feed=atom&action=historyLXF71:Subversion - История изменений2024-03-29T08:30:22ZИстория изменений этой страницы в викиMediaWiki 1.19.20+dfsg-0+deb7u3http://wiki.linuxformat.ru/wiki/index.php?title=LXF71:Subversion&diff=6791&oldid=prevYaleks: Новая: {{Цикл/Subversion}} == Subversion ветви, тэги и слияния == : ''чАстЬ 3 Грэхем моррисон объясняет, как управлять репози...2009-02-04T18:58:26Z<p>Новая: {{Цикл/Subversion}} == Subversion ветви, тэги и слияния == : ''чАстЬ 3 Грэхем моррисон объясняет, как управлять репози...</p>
<p><b>Новая страница</b></p><div>{{Цикл/Subversion}}<br />
== Subversion ветви, тэги и слияния ==<br />
: ''чАстЬ 3 Грэхем моррисон объясняет, как управлять репозитарием по мере того, как проект начинает расширяться''<br />
<br />
Это – финальная статья из цикла, посвященного системе<br />
контроля версий Subversion. После изучения базовых вопросов настройки, администрирования сервера и работы с клиентом Subversion, вы уже можете представить себе преимущества от<br />
использования данной системы в вашем проекте. Впрочем, спустя<br />
некоторое время вам потребуется некоторая дополнительная информация, касающаяся в первую очередь ветвей (branches). Именно об этом<br />
мы и поговорим сегодня.<br />
<br />
Мы будем использовать некоторые из предложенных ранее концепций, чтобы проиллюстрировать удачные решения на серверной стороне. они окажут некоторое влияние на то, как вы работаете со своим<br />
репозитарием Subversion, хотя все необходимые действия будут<br />
выполняться со стороны клиента. Вам также потребуется материал предыдущих лекций, поэтому можете освежить его, прежде чем переходить к данной статье.<br />
<br />
=== Лесоводство: повторение ===<br />
Настоящие деревья (те, что растут в лесу) имеют ветви. Ветви являются отростками от главного ствола дерева. Ветви Subversion играют аналогичную роль с одним небольшим отличием: со временем одна из них<br />
может сама стать стволом, что не так-то просто проделать в случае с<br />
реальным деревом. Ветви Subversion укрепляют процесс разработки, а<br />
не расшатывают его.<br />
<br />
Существует несколько причин для организации ответвлений от<br />
главной линии разработки. Самой распространенной из них является<br />
создание новой версии таким образом, чтобы позволить выпускать<br />
критичные исправления и для предыдущей. Например, для KDE 3.4<br />
вышло обновление, имеющее номер 3.4.1. оно устраняет некоторые<br />
ошибки, добавляет пару переводов, но не содержит в себе новых функций. Последние припасены для ближайшего «большого» обновления.<br />
<br />
Использование двух различных ветвей упрощает одновременную<br />
поддержку стабильной (выпускаемой) и разрабатываемой версий продукта. Исправления ошибок включаются в обе из них, тогда как новые<br />
функции появляются только в разрабатываемой ветви. Впрочем, особо<br />
важные изменения можно перенести назад в стабильную. Это означает,<br />
что разработчики могут спокойно претворять в жизнь свои идеи, не<br />
боясь испортить стабильную версию.<br />
<br />
=== этап 1 – Разветвляемся ===<br />
{{Врезка<br />
|Заголовок=Пузырение<br />
|Содержание=Subversion хранит каждую ревизию в виде отдельного<br />
дерева файловой системы, создавая логическую копию<br />
репозитария. По большей части, она состоит из символических ссылок на предыдущую версию. Это делает<br />
Subversion особенно эффективным: копируется не все, а<br />
только изменения между ревизиями.<br />
<br />
Это напоминает жесткую ссылку в терминологии<br />
Linux. Жесткая ссылка выглядит и ведет себя как обычный файл, но является лишь указателем на расположение файла на диске. По сути, имена файлов тоже являются жесткими ссылками, поскольку они не содержат<br />
никаких данных – только имя и указатель.<br />
<br />
Управление изменениями происходит в рамках процесса, известного в технических кругах как «пузырение»<br />
(bubble-up). К аждое изменение копируется в новый файл<br />
– это зародыш пузыря. Р евизия представляет собой полное дерево файловой системы, состоящее из копий<br />
измененных файлов и символических ссылок на немодифицированные данные. Subversion создает новую ссылку<br />
между отредактированным файлом и его родительским<br />
каталогом. Начиная с этого момента, ссылки продвигаются вверх по дереву файловой системы до тех пор,<br />
пока не достигнут ее корня. К ак только это случится, процесс считается завершенным.<br />
<br />
Для сравнения: в случае «ветвящегося» репозитария, CVS приходится открывать каждый файл в каталоге.<br />
|Ширина=300px}}<br />
[[Изображение:Img 71 95 1.png|thumb|История Subversion]]<br />
Ветвь удобно представлять себе как простую копию основного репозитария кода (main trunk), сделанную в определенный момент времени.<br />
Строго говоря, никто не мешает использовать вам для реализации<br />
задуманного и локальную копию, но в этом нет нужды. Для Subversion,<br />
ветвь – не более, чем копия, хотя исходный вариант ее истории изменений является общим с основным деревом. Это оказывает свое влияние на процесс создания ветви.<br />
<br />
Для иллюстрации мы по-прежнему будем использовать простое<br />
приложение «Здравствуй, мир» из предыдущих выпусков. О но состоит<br />
из маленького файла с исходным кодом (helloworld.cpp) и отвечающего ему файла Makefile. Сейчас они оба располагаются в одном каталоге, но по мере «ветвления» будут разнесены по разным веткам.<br />
<source lang="bash">$ svn mkdir branches<br />
A branches<br />
$ svn mkdir branches/stable_1_0<br />
A branches/stable_1_0<br />
$ svn mv helloworld.cpp branches/stable_1_0/<br />
A branches/stable_1_0/helloworld.cpp<br />
D helloworld.cpp<br />
$ svn mv Makefile branches/stable_1_0/<br />
A branches/stable_1_0/Makefile<br />
D Makefile</source><br />
Мы создали в нашей локальной рабочей копии каталог «branches»<br />
и разместили в нем подкаталог «stable_1_0», в котором будет хранится<br />
стабильная версия. Затем, в рамках подготовки к разветвлению кода,<br />
мы переместили оба файла в директорию stable_1_0. Следующим<br />
шагом будет копирование каталога, соответствующего ветви stable_1_0, в каталог, который отвечает нашей нестабильной разрабатываемой<br />
ветви. О днако, прежде чем Subversion позволит нам это сделать, необходимо зафиксировать (commit) предыдущие изменения.<br />
<source lang="bash">$ svn commit -m “Created new branch structure.”<br />
Deleting Makefile<br />
Adding branches<br />
Adding branches/stable_1_0<br />
Adding branches/stable_1_0/Makefile<br />
Adding branches/stable_1_0/helloworld.cpp<br />
Deleting helloworld.cpp<br />
Committed revision 5.</source><br />
Флаг -m позволяет вам прокомментировать фиксируемые изменения, не запуская внешний текстовый редактор. Т еперь, когда с предыдущими ревизиями покончено, можно начать разрабатываемую ветвь,<br />
сделав копию каталога stable_1_0.$ cd branches/<br />
<source lang="bash">$ svn copy stable_1_0 HEAD<br />
A HEAD<br />
$ svn commit<br />
Adding branches/HEAD<br />
Committed revision 6.</source><br />
В данном примере, мы использовали копию стабильной ветви<br />
(stable branch) для создания разрабатываемой (development branch), в<br />
которую планируется добавлять новые функции и исправления<br />
найденных ошибок. Поскольку мы идем во главе процесса разработки,<br />
назовем ее «HEAD».<br />
<br />
==== Управление доступом ====<br />
Создать новую ветвь просто. Самой важной частью является последующее управление ветвями, что обычно отдается на откуп политике проекта. Т еперь, когда проект разветвился, новые разработчики могут либо<br />
заняться исправлением ошибок, либо реализацией дополнительного<br />
функционала в HEAD.<br />
<br />
Если вы заботитесь о безопасности, то можете захотеть ограничить<br />
доступ к существующим ветвям и дать лишь некоторым участникам<br />
проекта право на создание новых. Чтобы предоставить избранным разработчикам права на модификацию тех или иных ветвей, для доступа к<br />
репозитарию необходимо использовать Apache. Причина этого состоит<br />
в следующем: наиболее простым способом разграничения доступа по<br />
пользователям является установка модуля Apache под названием<br />
mod_authz_svn.<br />
<br />
Теперь из каталога HEAD можно получить новую копию разрабатываемой ветви.<br />
<source lang="bash">$ svn checkout file:///usr/share/subres/branches/HEAD<br />
A HEAD/helloworld.cpp<br />
A HEAD/Makefile<br />
Checked out revision 6.</source><br />
История изменений для каталога HEAD будет распространяться<br />
назад лишь до точки ветвления. О днако, внутри каждой ветви, история<br />
изменения индивидуальных файлов будет перенесена из их прежнего<br />
местоположения. О тличие состоит в том, что helloworld.cpp сейчас скопирован в два каталога (содержится в двух ветвях). История изменения<br />
файла helloworld.cpp также будет разветвлена, чтобы хранить сведения<br />
для каждого файла по отдельности. В этом легко убедиться, просмотрев журнал команд. Ниже представлена урезанная версия вывода svn<br />
log helloworld.cpp для ветви HEAD:<br />
<source lang="bash">r7 | Added a cutting-edge feature.<br />
r6 | Added HEAD development branch.<br />
r5 | Moved project into a branch structure<br />
r4 | Resolved conflict by incorporating both changes.</source><br />
Как видите helloworld.cpp наследует историю со времени, предшествующего созданию ветви в момент r6. В зависимости от организации<br />
проекта, процесс добавления новых функций в HEAD может потребовать переноса некоторых исправлений ошибок и тому подобных вещей<br />
назад, в стабильную ветвь. Чтобы сделать это, нам придется слить<br />
(merge) изменения со стабильной ветвью.<br />
<br />
=== этАп 2 – сЛивАем одну ветвЬ с друГой ===<br />
[[Изображение:Img 71 96 1.png|thumb|Код в дереве разработки наследуется каждой последовательной версией<br />[1] оригинальная версия (1.0).<br />[2] исправления для оригинальной версии (1.1).<br />[3] Функции, запланированные для следующей версии (2.0).]]<br />
работа над тестовой ветвью часто подразумевает решение проблем,<br />
которые имеют отношение и к стабильной ветви, особенно если речь<br />
идет о безопасности. В нашем примере с helloworld.cpp в разрабатываемую ветвь была добавлена еще одна строка, выводящая надпись «a<br />
cutting-edge feature». конечно, в реальном случае изменения будут куда<br />
более серьезными, но обсуждаемые принципы останутся<br />
неизменными.<br />
<br />
Несмотря на общее происхождение, Subversion рассматривает эти<br />
два файла как полностью различные. В прошлый раз мы использовали команду svn diff для поиска различий между двумя ревизиями<br />
одного и того же файла. На сей раз перед нами стоит несколько другая задача: надо найти отличие между одним и тем же файлом, но<br />
принадлежащим двум разным ветвям. Для этого нам потребуется<br />
команда svn merge. Перво-наперво, необходимо сравнить изменения,<br />
произведенные в стабильной и разрабатываемой ветвях.<br />
<br />
Просматривая журнал для helloworld.cpp из стабильной ветви, становится очевидно, что здесь нет изменений, относящихся к разрабатываемой ветви:<br />
<source lang="bash">r5 | Moved project into a branch structure<br />
r4 | Resolved conflict by incorporating both changes.</source><br />
ревизии r6 и r7 ветки HEAD отсутствуют. как было видно из предыдущих листингов, r6 – это процесс копирования файлов в новую ветвь,<br />
а r7 – добавление новой, очень интересной функции (r7 | added a<br />
cutting-edge feature).<br />
разность между этими двумя ревизиями может быть определена с<br />
помощью svn diff:<br />
<source lang="diff">$ svn diff -r 6:7 file:///usr/share/subres/branches/<br />
Index: HEAD/helloworld.cpp<br />
=================<br />
--- HEAD/helloworld.cpp (revision 6)<br />
+++ HEAD/helloworld.cpp (revision 7)<br />
@@ -6,6 +6,7 @@<br />
{<br />
cout << “Hello World!” << endl;<br />
cout << “Both modified additions.” << endl;<br />
+ cout << “Cutting edge feature.” <<endl;<br />
return(0);<br />
}</source><br />
Единственное добавление – это «суперновая функция» («cutting<br />
edge feature»), отмеченная в листинге знаком «+», расположенным в<br />
начале строки. как мы видели в прошлом месяце, вывод svn diff можно<br />
использовать для создания патча. В случае с Subversion в этом нет<br />
необходимости, поскольку для применения всех необходимых изменений к вашей рабочей копии можно использовать команду svn merge.<br />
Начните с локальной копии файла helloworld.cpp и добавьте в него<br />
изменения, отвечающие нужным ревизиям:<br />
<source lang="bash">$ svn merge -r 6:7 file:///usr/share/subres/branches/HEAD/helloworld.cpp<br />
U helloworld.cpp<br />
$ svn status<br />
M helloworld.cpp</source><br />
Согласно нашему коду, изменения, сделанные в ветви HEAD, были<br />
перенесены в локальную копию того же файла, отмеченного буквой M<br />
в первой колонке вывода команды svn merge. теперь можно просмотреть эти изменения и зафиксировать их в стабильной ветви. Между<br />
слитой и оригинальной версиями может возникнуть конфликт, поэтому<br />
будьте внимательны, объединяя изменения между двумя ветвями.<br />
<br />
==== перемотка ====<br />
Использование номеров ревизий в качестве идентификаторов применяемых к вашему коду изменений может иметь нестандартные побочные эффекты. Например, их можно не указывать при переходе от<br />
одной ревизии к другой. Их также можно переворачивать. Написав<br />
«7:6» вместо «6:7», вы осуществите откат изменений седьмой ревизии<br />
до уровня шестой. В духе предыдущего примера, можно написать:<br />
<source lang="bash">svn merge -r 7:6 file:///usr/share/subres/branches/HEAD/helloworld.cpp<br />
G helloworld.cpp</source><br />
буква «G» обозначает, что Subversion удачно применил изменения,<br />
хранящиеся в репозитарии, к локальному файлу. Здесь уместно упомянуть команду svn revert, представляющую собой куда более безопасный<br />
метод для отката локально сделанных изменений и восстановления<br />
нужной версии из репозитария.<br />
<br />
Другим удобным трюком является смена ветви, которая соотвествует вашей локальной копии на сервере. Это достигается командой svn<br />
switch. На самом деле, она не делает ничего экстраординарного –<br />
просто подменяет URL, на который ссылается рабочая копия. текущий<br />
URL можно просмотреть с помощью команды svn info:<br />
<source lang="bash">$ svn info<br />
URL: file:///usr/share/subres/branches/stable_1_0</source><br />
В нашем примере можно изменить ветвь со stable_1_0 на HEAD,<br />
введя команду:<br />
<source lang="bash">$ svn switch file:///usr/share/subres/branches/HEAD<br />
U helloworld.cpp<br />
Updated to revision 7.<br />
$ svn info<br />
URL: file:///usr/share/subres/branches/HEAD</source><br />
<br />
=== чАстЬ 3 – КЛеймЛение ===<br />
Ветви сторонних поставщиков (vendor banches) позволяют включать в<br />
ваш проект разработки других людей, например, внешние библиотеки.<br />
С помощью ветвей поставщиков можно следить за изменениями в других проектах и, более того, быть уверенным, что все ваши разработчики<br />
используют одну и ту же версию. CVS имеет специальную поддержку<br />
для ветвей сторонних поставщиков, однако, Subversion достаточно универсален, чтобы интегрировать их без особых трудов.<br />
<br />
Ветвь стороннего поставщика обычно существует в своей структуре каталогов под общим корнем репозитария Subversion. Ее часто размещают в директории с названием «vendor» - отсюда и название<br />
«vendor branch». В этот каталог необходимо импортировать весь сторонний проект целиком. когда выходит новая версия данного продукта, необходимо применять все изменения к текущей рабочей версии,<br />
чтобы ваши собственные правки не потерялись. После этого можно<br />
зафиксировать изменения в репозитории с тем, чтобы другие разработчики получили возможность использовать более новую версию<br />
стороннего приложения.<br />
<br />
==== игры с тегами ====<br />
{{Врезка<br />
|Заголовок=нАш совет<br />
|Содержание=<br />
; структурируйте репозитарий<br />
<br />
Структура файловой системы<br />
лежит целиком на плечах главы<br />
проекта, но при ее создании полезно иметь в виду следующие вещи.<br />
<br />
Если в одном репозитарии разрабатываются разные приложения,<br />
разумно завести для них отдельные каталоге верхнего уровня.<br />
Подумайте, как будет происходить<br />
управление ветвями и тегами.<br />
большинство проектов используют<br />
каталог «trunk» в качестве основного дерева разработки, а затем<br />
создает теги и ветви на одном<br />
уровне с ним. Это, конечно, не<br />
единственный способ – все зависит<br />
только от вас.<br />
|Ширина=200px}}<br />
Для эффективного использования ветви стороннего поставщика необходимо быть уверенным, что она не может быть изменена. В терминах<br />
системы контроля версий это известно как «теггинг» (tagging), а с точки зрения Subversion, это просто ветвь, которую нельзя редактировать.<br />
как и ветвь, тег (tag) – это копия репозитария, сделанная в некоторый<br />
момент времени. тег похож на установку точки ревизии, более того, так<br />
оно и есть, однако, на него возлагаются некоторые дополнительные<br />
функции. тег - хороший способ отметить прохождение контрольной<br />
точки в цикле разработки.<br />
<br />
одной из главных причин для создания тега является выпуск важной версии, например, stable_1_0 в нашем примере. как и ветви, теги<br />
– не более чем копии репозитария, и для их создания можно использовать команду svn copy. Единственным отличием является необходимость явно указать создание тега в комментарии к ревизии и запрет на<br />
редактирование помеченных ветвей со стороны других разработчиков.<br />
<br />
Чтобы сделать тег в нашем предыдущем примере, выполните<br />
следующие команды:<br />
<source lang="bash">$ svn mkdir file:///usr/share/subres/tags<br />
Committed revision 8.<br />
$ svn copy file:///usr/share/subres/branches/stable_1_0 file:///usr/share/subres/tags/release_1<br />
Committed revision 9.</source><br />
такой подход обладает очевидным недостатком: ничто не мешает разработчику взять и изменить содержимое данной директории. В большинстве случаев это не проблема, так как «неприкосновенность» тегов регулируется политикой проекта. однако, в случае необходимости вы можете<br />
«затянуть гайки».<br />
<br />
Это потребует от нас перейти к первом руководству из данной серии,<br />
поскольку для решения данной проблемы используются ловушки (hooks)<br />
системы Subversion. Напомним, что ловушка – это сценарий, который<br />
выполняется в качестве реакции на некоторое событие. С их помощью<br />
можно легко отменить изменения, случайно сделанные в отмеченной тегом<br />
ветви. кроме этого, можно использовать уже упоминавшийся ранее модуль<br />
mod_authz_svn.<br />
<br />
И вот оно, долгожданное окончание! C’est tout. Je suis un sandwich! я<br />
надеюсь, что этого краткого введения хватит не только для поддержания своего собственного сервера, но и для полноценного участия в других проектах. Если этот проект будет успешным, вам непременно придется объединять изменения и выполнять прочие описанные здесь<br />
операции, двигая вперед весь цикл разработки.<br />
<br />
{{Врезка|center|<br />
|Заголовок=удАЛенный доступ К проеКту с помоЩЬю SVNSERVE<br />
|Содержание=<br />
[[Изображение:Img 71 97 1.jpg|thumb|после запуска svnserve с сервером можно будет работать из Konqueror.]]<br />
В первом руководстве данной серии было показано, как использовать модуль Apache для обеспечения удаленного доступа. Но мы также можем<br />
использовать для этих целей протокол svn://.<br />
Серверное приложение, ответственное за предоставление такой возможности, называется svnserve<br />
и является частью стандартной установки<br />
Subversion. По умолчанию оно не используется,<br />
поскольку предназначается преимущественно для<br />
решения небольших, нетребовательных задач, но в<br />
этом случае может оказаться стоящей альтернативой Apache.<br />
<br />
Запустить сервер очень просто. Введите команду с парой параметров (режимом работы и путем к<br />
репозитарию):<br />
svnserve -d -r path_to_repository<br />
Это запустит сервер в режиме демона (альтернативой является использование Internet Daemon,<br />
известного также как inetd). Путь к репозиторию указывается опцией -r. После запуска сервера вы можете сразу же получить к нему доступ по протоколу<br />
svn:<br />
svn co svn://localhost<br />
По умолчанию, svnserve предоставляет анонимный доступ в режиме «read-only». Это поведение<br />
можно изменить, отредактировав файл svnserve.<br />
conf, расположенный в конфигурационном каталоге<br />
репозитария. Этот файл хорошо документирован.<br />
<br />
разрешение и запрет анонимного доступа<br />
производится в секции [general.<br />
<br />
Чтобы контролировать доступ на уровне<br />
отдельных пользователей, включите эту возможность в поле Auth-access, укажите в<br />
password-db путь к файлу с паролями и<br />
создайте этот файл. Например:<br />
<source lang="ini">svnserve.conf:<br />
[general]<br />
anon-access = none<br />
auth-access = write<br />
password-db = passwd<br />
passwd:<br />
[users]<br />
graham = grahampassword</source><br />
После этого при доступе к репозиторию нужно будет указывать имя пользователя, добавляя<br />
его к адресу сервера, и вводить пароль.<br />
svn co svn://graham@localhost<br />
Недостаток описанного выше метода состоит в<br />
том, что пароли отправляются открытым текстом.<br />
Это представляет собой угрозу безопасности. Для<br />
устранения данной проблемы следует использовать<br />
вездесущий SSH, чтобы защитить соединение между клиентом и сервером. Все, что вам потребуется –<br />
это установить SSH и создать учетную запись на<br />
сервере. Sunserve запускается при подключении<br />
пользователя, так что его не обязательно постоянно<br />
держать в памяти. однако, клиенту необходимо явно<br />
указать путь к репозитарию на файловой системе<br />
сервера. Например:<br />
svn co svn+ssh://graham@localhost/usr/share/subres<br />
|Ширина=}}</div>Yaleks