Subversion или SVN

С точки зрения пользователя хранилище Subversion представляет собой «двумерную» файловую систему. Объекты в хранилище (файлы и директории) идентифицируются двумя «координатами»: именем и номером ревизии. Другими словами, хранилище представляет собой массив мгновенных снимков (ревизий) дерева файлов и директорий, индексируемый номером ревизии. Каждый такой снимок — обычная (одномерная) файловая система.

При необходимости указания на конкретную ревизию объекта используется запись вида: имя@ревизия, например, /main.c@29 — файл /main.c в ревизии 29. Такое указание ревизии, используемое для уточнения имени, называется стержневая ревизия (англ. peg revision).

 

Имена файлов
Имя объекта файловой системы в Subversion образуется по тем же правилам, что и в UNIX-подобных операционных системах: существует только одна корневая директория, элементы пути разделяются косой чертой («/»). Объектами файловой системы являются файлы и директории (а также символические ссылки, которые эмулируются из обычных файлов путём установки атрибута svn:special)

Номер ревизии используется в двух различных контекстах:

оперативной ревизии (англ. operative revision);
стержневой ревизии (англ. peg revision).

Ревизия называется оперативной, если она указывает ревизию или диапазон ревизий, к которому должна быть применена операция, например:

svn log -r 199:230 http://some.path

В данном примере выполняется команда svn log для диапазона ревизий 199:230, который и является диапазоном оперативных ревизий.

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

svn log -r 29:33 http://some.path/bar.txt

В команде указан диапазон оперативных ревизий (29:33), но области, выделенные на рисунке голубым и зелёным фоном, в равной степени можно считать историей файла /bar.txt в диапазоне ревизий 29:33. В подобных случаях необходимо указывать ещё и стержневую ревизию для разрешения неоднозначности. Стержневая ревизия — это номер ревизии, указанный в дополнение к URL объекта файловой системы (используется запись вида «URL@ревизия»). Название происходит от английского слова peg, которое можно перевести как «стержень» или «колышек». Стержневая ревизия отмечает ту цепочку состояний, которой принадлежит указанная пара URL@ревизия и, таким образом, однозначно идентифицирует объект хранилища, к которому должна быть применена команда. В приведённом ниже примере первая команда выведет историю, выделенную на рисунке голубым фоном, а вторая — историю, выделенную зелёным фоном:

svn log -r 29:33 http://some.path/file.txt@32
svn log -r 29:33 http://some.path/bar.txt@34

В качестве стержневой ревизии следует указывать как можно более позднее состояние интересующего объекта. Причина этого в том, что цепочка состояний однозначно отслеживается «назад», но не «вперёд». Например, URL со стержневой ревизией http://some.path/foo.txt@31 принадлежит двум цепочкам состояний (выделены соответственно зелёным и серым фоном). Из этих двух цепочек указанный URL адресует серую цепочку, то есть при движении «вперёд» от стержневой ревизии операции копирования игнорируются.
Операции над файловой системой

Над объектами файловой системы в хранилище Subversion могут быть произведены перечисленные ниже операции[33] (см. рис. 1). В скобках указано краткое именование операции в обозначениях команды svn status.

Добавление (A). Добавление объекта в файловую систему. Добавленный объект не имеет истории ревизий. Пример на рисунке:

файл /main.c был добавлен в ревизии 27.

Модификация (M). Модификация объекта, например, изменение содержимого файла или изменение свойств файла или директории. Пример на рисунке:

файл /main.c был модифицирован в ревизии 28.

Удаление (D). Удаление файла из головной и последующих ревизий. При этом файл остаётся в предыдущих ревизиях. Пример на рисунке:

файл /main.c был удалён в ревизии 30.

Добавление с историей (A+). Представляет собой копирование объекта внутри файловой системы хранилища, то есть объект имя_источника@ревизия_источника копируется в имя_копии@HEAD. Скопированный объект наследует от источника историю ревизий до момента копирования (наследование истории показано на рисунке пунктирными связями). Примеры на рисунке:

в ревизии 29 директория /tags/R1 была скопирована с директории /trunk@27;
в ревизии 31 файл /main.c был скопирован с /main.c@29, то есть с более ранней ревизии самого себя, таким образом, произведено восстановление ранее удалённого (в ревизии 30) файла с сохранением истории ревизий.

Замена (R+). Имеет место в случае, когда в одной ревизии произведено и удаление объекта (D), и добавление с историей (A+) объекта с тем же самым именем. Хотя имя при операции замены остаётся неизменным, Subversion рассматривает объект до и после замены как два различных объекта с различными историями ревизий (история старого заканчивается в точке замены, история нового наследуется от источника копирования и продолжается далее). Пример на рисунке:

в ревизии 30 файл /file.txt был заменён: старый файл /file.txt удалён, а новый файл с тем же именем скопирован с файла /bar.txt@29.

Рабочая копия

Рабочая копия — это созданная клиентской программой Subversion локальная копия части данных из хранилища, содержащая помимо собственно данных некоторую служебную информацию (скрытые директории с именем .svn). Служебная информация необходима для правильного функционирования рабочей копии; что-либо менять в служебных данных нельзя. Минимальной единицей данных, которую можно получить из хранилища как рабочую копию, является директория. Содержимое директории можно извлечь не полностью: например, можно исключить отдельные файлы или поддиректории. Однако извлечь из хранилища отдельный файл как рабочую копию невозможно.

Любая поддиректория рабочей копии Subversion 1.6 и более ранних версий также является полноценной рабочей копией, поскольку в каждой директории хранятся её служебные данные (каталоги .svn). Начиная с версии 1.7 в каждой рабочей копии присутствует только одна директория .svn в корне её каталога.

Рабочая копия является самодостаточной в том смысле, что Subversion не хранит каких-либо данных, относящихся к рабочей копии, вне её. Поэтому, имея одну рабочую копию, можно сделать ещё несколько копий простым копированием без затрат сетевого трафика.

В служебных директориях рабочей копии, помимо прочего, хранится так называемая чистая копия (англ. pristine copy) — файлы рабочей копии в неизменённом виде, как они были извлечены из хранилища (для svn это ревизия с именем BASE). Наличие чистой копии позволяет быстро и без обращения к хранилищу выполнять операции просмотра и отката локальных изменений. Однако размер рабочей копии на диске примерно в два раза больше (данные + чистая копия данных), чем размер самих данных. Такой подход обусловлен тем, что дисковые ресурсы дешевле и доступнее, чем ресурсы сети передачи данных.

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

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

Атомарность фиксаций (англ. atomic commits) — изменения в нескольких файлах или директориях фиксируются единой транзакцией порождая при этом одну ревизию. В случае неудачной фиксации, при любом сбое или ошибке, система гарантирует, что хранилище не окажется в частично изменённом состоянии — в хранилище попадут либо все изменения, либо (при неудаче) — ни одного.
Изоляция гарантирует, что промежуточные состояния хранилища внутри транзакции не видны другим транзакциям и пользователям. Например, если один пользователь фиксирует одной транзакцией изменения в нескольких файлах, то другие пользователи не могут увидеть такого состояния хранилища, в котором часть файлов уже изменена, а часть — не изменена.

Данные свойства не гарантируются для рабочей копии Subversion — она, в отличие от хранилища, при сбое или прерывании может оказаться в промежуточном или заблокированном состоянии (то есть перед продолжением работы её потребуется восстановить командой svn cleanup или пересоздать заново).
Локальные и удалённые формы команд

Все команды клиента Subversion можно разделить на следующие группы:

модифицирующие рабочую копию;
модифицирующие хранилище;
модифицирующие и рабочую копию, и хранилище;
не модифицирующие ничего.

Ветвление

Ветвление является важным аспектом работы систем управления версиями, поскольку типичные приёмы[38] управления версиями (по крайней мере, при разработке программного обеспечения) включают в себя использование ветвей. Subversion обладает достаточно развитыми возможностями для ветвления и слияния (однако не поддерживает слияние переименованных файлов и директорий).

Настройка сервера

Настроить сервер — SVN репозитарий, довольно просто, в данном примере, директория, /home/svn/, должна существовать:

# svnadmin create —fs-type fsfs /home/svn/project1

Подключиться к репозитарию можно следующими способами:

file:// — Прямой доступ через файловую систему с помощью SVN клиента. В локальной файловой системе должны быть корректно настроены привилегии.
svn:// или svn+ssh:// — Удаленный доступ к SVN серверу (так-же по протоколу SSH). Требуются права в локальной файловой системе, порт по-умолчанию: 2690/tcp.
http:// Удаленный доступ через webdav, используя apache. Для данного метода не требуется наличие локальных пользователей.

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

# svn import /project1/ file:///home/svn/project1/trunk -m ‘Initial import’
# svn checkout file:///home/svn/project1

Удаленный доступ по протоколу SSH

Удаленный доступ по протоколу SSH не требует каких-то доаолнительных настроек, просто замените file:// на svn+ssh/hostname. Например:
# svn checkout svn+ssh://hostname/home/svn/project1

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

# groupadd subversion # groupmod -A user1 subversion # chown -R root:subversion /home/svn # chmod -R 770 /home/svn

Типичные SVN команды

# svn co http://host.url/svn/project1/trunk # Оформить заказ на последнюю версию
# Тэги и ветки создаются с помощью копирования
# svn mkdir http://host.url/svn/project1/tags/ # Создать директорию tags
# svn copy -m «Tag rc1 rel.» http://host.url/svn/project1/trunk \
http://host.url/svn/project1/tags/1.0rc1
# svn status [—verbose] # Проверить состояние файлов в рабочей директории
# svn add src/file.h src/file.cpp # Добавить два файла
# svn commit -m ‘Added new class file’ # Передать изменения сообщением
# svn ls http://host.url/svn/project1/tags/ # Список всех тэгов
# svn move foo.c bar.c # Переместить (переименовать) файлы
# svn delete some_old_file # Удалить файлы

Рабочий цикл

Типичная итерация рабочего цикла с Subversion включает следующие этапы.

  • Обновление рабочей копии из хранилища (svn update) или её создание (svn checkout).
  • Изменение рабочей копии. Изменения директорий и информации о файлах производится средствами Subversion, в изменении же (содержимого) файлов Subversion никак не задействован — изменения производятся программами, предназначенными для этого (текстовые редакторы, средства разработки и т. п.):
    • новые (ещё не зафиксированные в хранилище) файлы и директории нужно добавить (команда svn add), то есть передать под управление версиями;
    • если файл или директорию в рабочей копии нужно удалить, переименовать, переместить или скопировать, необходимо использовать средства Subversion (svn mkdir, svn delete, svn move, svn copy);
    • просмотр состояния рабочей копии и локальных (ещё не зафиксированных) изменений (svn info, svn status, svn diff);
    • любые локальные изменения, если они признаны неудачными, можно откатить (svn revert).
  • При необходимости — дополнительное обновление, для получения изменений, зафиксированных в хранилище другими пользователями и слияния этих изменений со своими (svn update).
  • Фиксация своих изменений (и/или результатов слияния) в хранилище (svn commit).