@ Карта сайта News Автора!

Bog BOS: subversion (svn) - система управления версиями

Последние изменения:
2017.04.19: hard: АВР от APC

Последнее изменение файла: 2014.12.26
Скопировано с www.bog.pp.ru: 2017.04.30

Bog BOS: subversion (svn) - система управления версиями

subversion (svn) - открытая система управления версиями файлов и каталогов проектов с центральным репозиторием и сетевым доступом.

Система управления версиями (VCS, version control systems) предназначена для хранения всех версий исходных файлов проекта (не результатов компиляции и сборки) и обеспечения возможности одновременной работы с одними и теми же файлами проекта для множества участников. Работа с ветвями позволяет сопровождать несколько версий проекта одновременно.

Разработка начата в 2001 году фирмой CollabNet Inc как "CVS без ошибок и ограничений" под лицензией совместимой с Debian Free Software Guidelines. В настоящее время перешёл к Apache Software Foundation (лицензия Apache 2.0). Текущая версия 1.8.11 (декабрь 2014). В RHEL5 пакет subversion.x86_64 и mod_dav_svn.x86_64 версии 1.4.2-4.el5_3.1 (новые версии на rpmforge). В FC10 - subversion.x86_64 и mod_dav_svn.x86_64 версии 1.6.5-1.fc10.1. В RHEL6: svnkit и eclipse-svnkit 1.3.0, kdesvn 1.5.5, subversion и mod_dav_svn 1.6.11, cvs2svn 2.3.0, rapidsvn 0.12.0, websvn 2.3.3.

Основы

Имеющийся каталог проекта ставится под контроль системы управления версиями импортированием каталога в репозиторий. Обратная операция - экспорт каталога из репозитория. При редактировании файлов репозитория используется модель copy-modify-merge (противоположность lock-modify-unlock):

  1. из репозитория извлекается рабочая копия (выгрузка, checkout)
  2. в рабочую копию вносятся локальные изменения (изменение файловой структуры необходимо делать с помощью команд svn)
  3. изменённая рабочая копия сохраняется в репозиторий (фиксация изменений, commit, единая транзакция, номер ревизии репозитория увеличивается на 1)

Если сохранить рабочую копию невозможно из-за изменений, внесённых другими за истекший промежуток времени, то пользователь должен извлечь накопившиеся изменения из репозитория в рабочую копию (update) с автоматическим или ручным двухпозиционным слиянием (diff) своих и чужих изменений, затем попытаться сохранить результат слияния в репозиторий (пока там ещё кто-нибудь не внёс изменения). Рабочую копию можно использовать для последующего редактирования файлов.

Все зафиксированные изменения файлов и каталогов (версии, ревизии) в репозитории хранятся вечно. Изменения репозитория являются атомарными (неделимыми), представляются в виде неделимого набора изменений файлов и каталогов. Номер ревизии является общим для всего репозитория, а не для файла или каталога. Сервер не отслеживает рабочие копии. Внутри рабочей копии хранятся метакаталоги (.svn) и могут быть "посторонние" файлы. С рабочей копией не стоит обращаться как с обычными файлами (разве что можно удалить после фиксации изменений), а копировать только через фиксацию и выгрузку. Репозиторий не стоит рассматривать как удалённое файловое хранилище. При обновлении из репозитория текущие изменения рабочей копии не записываются в репозиторий, а при записи в репозиторий не производится обновление, в результате файлы рабочей копии имеют различные номера версии.

subversion позволяет работать не только с последовательностью ревизий проекта, но и с деревом ревизий (расщепление). К сожалению, это дерево является виртуальным (воображаемым), т.к. в subversion ревизии реализованы с помощью механизма "быстрого копирования подкаталогов" и на посторонний взгляд неотличимы от подкаталогов проекта. Отображение дерева каталогов на дерево ревизий необходимо производить "в уме". Это обеспечивает гибкость при выборе методики использования (структуры ветвей, подпроекты, несколько проектов в репозитории) за счёт усложнения рабочих процедур (и потере понимания происходящего у некоторых участников: команда копирования используется как для копирования каталога, так и для создания ветви; команда слияния используется как для внесения изменений в исходной ветви в новую, так и для возврата изменений новой ветви в исходную). Конфликты слияния ревизий (наложение разности ревизий на целевую ревизию, трёхпозиционное слияние, diff3) разрешаются аналогично конфликтам фиксации изменений. В версии 1.5 реализована поддержка слияния (объединения, merge) ветвей в виде сохранения информации о проведённых слияниях и учёта их в дальнейшем.

Архитектура и особенности subversion

Клиентские приложения (командной строки - svn, svnversion; графические, встроенные в систему разработки - Eclipse, расширители менеджера файлов - TortoiseSVN) через API интерфейса клиента вызывают фукции клиентской библиотеки subversion, которая хранит рабочую копию проекта (с помощью библиотеки управления рабочей копией) и взаимодействуют (Repository Access, RA) с репозиторием subversion

К одному репозиторию можно обращаться одновременно различными способами. Рекомендуется завести отдельного пользователя (svn) и приписать все файлы репозитория и процессы сервера ему. Обслуживающие программы: svnadmin, svnlook, svndumpfilter, svnsync.

Каждый репозиторий имеет уникальный UUID, котрый используется клиентами для проверки. Имена файлов и сообщения журнала хранятся в UTF-8. При синхронизации рабочей копии используются механизмы журнализации (для предотвращения проблем с неполной синхронизацией) и блокировки (для предотвращения одновременных изменений несколькими клиентами). При хранении репозитория используется модель моментальных снимков, разница между последовательными ревизиями представляется как заплатка (patch, сжатая в версии 1.4), а сама ревизия как последовательность заплаток, создающая дерево файлов. В версии 1.6 группы старых ревизий (по 1000 штук) упаковываются в пакеты для ускорения доступа.

Рабочая копия хранится на хосте пользователя как дерево каталогов файлов проекта и административный каталог '.svn' для каждого каталога проекта, в котором для каждого файла хранится время извлечения из репозитория и номер ревизии репозитория, на которой он основан. Здесь же (.svn/text-base/) кешируются исходные версии всех файлов и исходные метаданные (.svn/prop-base и .svn/dir-prop-base), что позволяет откатывать изменения и делать отчёты без сетевого соединения, а также сохранять изменения в виде разности файлов (delta). Если его случайно испортить, то придётся удалять каталог рабочей копии и обновлять её (svn update). При синхронизации делается временная копия в .svn/tmp (при сбое становится постоянной ;). Таким образом требуется троекратный объём файлового пространства.

Аутентификация по требованию сервера с кешированием в ~/.subversion/auth/ (хост, порт, область действия), т.е. если производится checkout на каталог, который доступен анонимному пользователю, то аутентификация не производится и закрытые для анонимного пользователя подкаталоги не будут считаны. При кешировании паролей может использоваться GNOME Keyring или KDE Wallet или они хранятся в открытом виде.

Обеспечивается работа с ветвями проектов (branch, независимые линии разработки проектов, имеющие общую историю) и отмеченными версиями (tag, неизменяемый слепок), что требуется для одновременной поддержки несколько версий проекта. Ответвлять можно как от основного ствола (trunk), так и от одной из предыдущих веток. Реализовано как копирование дерева файлов проекта (имя-проекта/trunk) в отдельный каталог (имя-проекта/branches/имя-ветви), в системе нет понятия "ветвь" и "отмеченная версия", но есть хранение истории происхождения и поддержка копирования изменений между исходным деревом и ветвью (merging). Возможна "вывернутая" файловая иерархия: trunk/имя-проекта, branches/имя-проекта/имя-ветви. При использовании другой файловой иерархии придётся дополнительно обучать новичков и дорабатывать стороннее ПО.

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

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

При обработке текстовых файлов в момент синхронизации возможна замена ключевых слов на стороне клиента текущими значениями (ищутся и заменяются шаблоны '$КлючевоеСлово$' или '$КлючевоеСлово: ... $'):

При указании объекта может быть использована уточняющая версия (peg, записывается после имени объекта и символа '@'), которая позволяет различать объекты, которые в процессе развития проекта имели одно и то же имя (поиск всегда идёт назад по времени). По умолчанию, уточняющей версией для рабочей копии является BASE (ревизия на момент последней выгрузки), а для репозитория - HEAD (последняя ревизия на данный момент).

В версии 1.5 реализован механизм пометок файлов рабочей копии под названием changelists (одна метка на файл). Можно помечать файлы, удалять пометки, ограничивать множество затрагиваемых операциями файлов по наличию пометок.

Предполагается, что изменения в файлах доступны для слияний (программы, тексты, но не звук или видео), в противном случае предлагается использовать механизм блокировок: файл блокируется специальной командой создания замка (в рабочей копии д.б. последняя ревизия; замок хранит имя владельца и уникальный идентификатор, который сообщается владельцу; замок кешируется в рабочей копии; любой может извлечь из репозитория командой info); при попытке сохранить или удалить этот файл система требует предъявить идентификатор замка (при успехе все найденные локальным клиентом замки уничтожаются); замок можно снять специальной командой или сломать (администратор может сделать это непосредственно утилитами svnlook и svnadmin, обычный пользовать с помощью опции --force) или украсть (перевести на себя). Т.е. замок надо рассматривать не как охранное устройство, а как средство коммуникации.

Рекомендуемая методика работы (увеличивает вероятность раннего обнаружения проблемы, облегчает изучение истории проекта) для недебютной фазы разработки: исправление каждой ошибки или добавление функции (задача в системе управления заявками, issue tracking) делается в отдельно создаваемой ветке (имя ветви составляется по номеру заявки), перед фиксацией полезно обновить рабочую копию (или слить от ствола) и проверить предполагаемые изменения ("svn status" и "svn diff|less"), чтобы откатить случайный мусор (отладочная печать, изменения форматирования), при фиксации изменений в комментарий включается номер заявки (для Trac - #номер), длинный комментарий - повод для разбиения фиксации, по завершении заявки выполняется тест регрессии, при удачном прохождении теста изменения ветви сливаются в основной ствол, после тяжелого слияния тест регресии необходимо повторить, ветка удаляется.

Репозиторий

При создании репозитория рекомендуется хранить каждый проект в отдельном каталоге верхнего уровня, в котором завести подкаталоги trunk (основная линия разработки проекта), branches (временные для экспериментов или постоянные для доработки поставляемых версий ветви проекта), tags (поставляемые версии проекта), vendor (для чужих библиотек). В противном случае, возникнут проблемы приложениями, расширяющими возможности subversion, которые на это рассчитаны (subversion не отличает обычного копирования файла или каталога от создания ветви).

Можно иметь отдельный репозиторий на каждый проект, что увеличивает затраты на обслуживание, усложняет обмен между проектами, но позволяет каждому проекту иметь индивидуальные настройки (правила синхронизации, получатели извещений).

Поддерживаются следующие форматы хранения (backend, имеются средства конвертирования):

Структура каталога:

Утилита svnadmin позволяет обслуживать репозиторий (только локальный доступ), основные ключи:

Команды svnadmin:

Проверка целостности репозитория:

svnadmin dump --incremental -r0:HEAD репозиторий > /dev/null

Утилита svnlook позволяет проверять ревизии и транзакции (недоделанные ревизии), не вносит изменений, используется скриптами (hooks) и для диагностики, только локальный доступ. В качестве параметров указывается команда (help, youngest, info, changed, dirs-changed, author, date, log, history, diff, lock, cat, tree, proplist, propget, uuid), каталог и опции (--revision, --transaction, --verbose, --xml, --revprop).

Утилита svndumpfilter читает поток в переносимом формате с stdin, вырезает из него относящиеся (или неотносящиеся) к указанному поддереву данные и записывает на stdout. Первым параметром указывается команда: include или exclude. Вторым параметром - поддерево. Следует обратить внимание на наличие или отсутствие косой черты в начале имени - svnadmin dump её не выводит, а svndumpfilter выводит в отчёте. Не переваривает переименования поддерева (см. svndumpfilter2). Опции:

Утилита svnsync позволяет на ходу копировать все изменения, вносимые в исходный репозитоорий, в резервный репозиторий (с версии 1.5 можно синхронизировать поддерево). Не требуются права записи в исходный репозиторий. На время копирования желательно запретить прочие изменения в резервный репозиторий (например, с помощью скриптов pre-revprop-change и start-commit). Должно быть разрешено изменение метаданных для резервного репозитория (pre-revprop-change). Для продолжения синхронизации после аварийного прерывания может потребоваться удалить метаданные svn:sync-lock из ревизии 0. Синхронизацию в реальном времени можно обеспечить с помощью скриптов post-commit и post-revprop-change в исходном репозитории, запускающих svnsync. Команды (общие опции: --config-dir, --source-username, --source-password, --sync-username, --sync-password, --non-interactive, --trust-server-cert, --no-auth-cache, --quiet):

Утилита fsfs-reshard.py перетряхивает файловую структуру db/ с целью ускорения доступа.

Apache 2 как сервер subversion

Для обмена между клиентом и сервером используется протокол WebDAV/DeltaV (http://). Для шифрования можно использовать протокол SSL/TLS (https://). Протокол HTTP без сохранения состояния (stateless) менее эффективен, чем протокол SVN. Рекомендуется завести отдельного пользователя (svn) и приписать все файлы репозитория и процессы сервера ему. Сервер Apache 2 (пакет httpd) должен загрузить модули mod_dav, mod_dav_svn и mod_authz_svn (пакет mod_dav_svn):

LoadModule dav_module     modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

Описание репозитория (репозиториев):

<Location /svn>
   DAV svn
   SVNPath имя-каталога # права доступа должны соответствовать пользователю сервера Apache
# если в каталоге несколько репозиториев
#  SVNParentPath имя-каталога
</Location /svn>

Доступ на чтение к последней ревизии репозитория доступен с помощью любого броузера (для Firefox есть также расширение webdabfolder). Тип MIME извлекается из svn:mime-type (по умолчанию, text/plain) или mount.davfs. gvfs тоже смог бы, если бы не начал запрашивать родительский каталог.

Директива SVNReposName позволяет задать имя репозитория для заголовка.

Директива SVNListParentPath позволяет показывать список репозиториев при использовании SVNParentPath.

Директива SVNIndexXSLT с указанием URI XSLT шаблона позволяет оформлять оглавления каталогов (пример - tools/xslt/svnindex.xsl и svnindex.css, их необходимо положить в указанное место сайта - не в /svn!).

Директива SVNAutoversioning позволяет обычным WebDAV клиентам записывать в репозиторий, при этом каждый раз создаётся новая ревизия (и не одна!). Не стоит забывать об автосохранении, встроенном в обычные редакторы.

Директива ModMimeUsePathInfo позволяет автоматически задавать svn:mime-type.

Директива SVNAllowBulkUpdates позволяет запретить клиентам запрашивать информацию об изменениях в виде одного огромного массива.

Аутентификация и авторизация пользователей производится средствами Apache, с помощью модуля authz_svn_module, например (внутри Location):

# рекомендуется только под SSL/TLS
      AuthType Basic
# имя области
      AuthName "Subversion repository"
# заполняется утилитой "htpasswd -[c]m файл пользователь"
      AuthUserFile /etc/httpd/conf/svn.htpasswd 
# отключить проверку авторизации путей внутри запросов (ускоряет работу в 1.5 раза)
#     SVNPathAuthz off
# описание прав доступа
      AuthzSVNAccessFile /etc/httpd/conf/svn.access
# пускаем анонимусов
#     Satisfy Any
# совсем не пускаем анонимусов
#     AuthzSVNAnonymous Off
# ограничиваем любой доступ известными пользователями
#     Require valid-user
# ограничиваем запись известными пользователями
   <LimitExcept GET PROPFIND OPTIONS REPORT>
      Require valid-user
   </LimitExcept>

Файл с описанием прав доступа имеет строчную структуру и делится на секции, секция начинается с имени секции в квадратных скобках, комментарии начинаются с символа '#', строка содержит имя параметра, символ '=' и значение.

Секция groups описывает принадлежность пользователей к группам. Имя параметра задаёт имя группы, значение содержит список имён пользователей через запятую.

Секция aliases позволяется задавать синонимы пользователей (очень полезно для LDAP имён). При использовании синонимов их необходимо предварять символом '&'.

Имена остальных секций задают каталог репозитория, для которого определяются права доступа (до версии 1.7 символы в именах приводились к строчному регистру). Если область HTTP сервера содержит несколько репозиториев (SVNParentPath), то имя репозитория предваряет имя каталога (в качестве разделителя служит символ ":"). В данной секции в качестве имени параметра указывается имя пользователя или имя группы (предваряется символом '@') или шаблон '*', в качестве значения - строки "r" (этому пользователю разрешено читать) и "rw" (этому пользователю разрешено писать) или пусто (доступ запрещён). Права доступа к подкаталогу наследуются от прав доступа к каталогу, дополнительные права доступа к подкаталогу дополняют или перекрывают права доступа к каталогу. Права доступа для группы не перекрываются индивидульными правами доступа, а объединяются (нельзя отнять данные пользователю права с использованием групп).

Журнал svn (обычные запросы в этот журнал не попадут):

CustomLog logs/svn_logfile "%h %u %t %b \"%{User-Agent}i\" %v %{Host}i %{SVN-ACTION}e" env=SVN-ACTION

Имеется возможность репликации master-slave (с помощью mod_proxy).

Настройка SELinux:

chcon -R -t httpd_sys_content_t /data/svn

svnserve - выделенный сервер

Для обмена между клиентом и сервером используется протокол SVN (TCP/3690, stateful, svn://), быстрее WebDAV. Аутентификация и авторизация средствами SASL, соответственно возможен список пользователей, отличный от системного. Авторизация с точностью до имени файла. Шифрование средствами SASL. Рекомендуется завести отдельного пользователя (svn) и приписать все файлы репозитория и процессы сервера ему. Конфигурационный файл определяется относительно указанного клиентом репозитория: conf/svnserve.conf. Запускается как сервис или с помощью inetd (xinetd). Ключи:

Конфигурационный файл имеет строчную структуру, строка содержит имя параметра, символ '=' и значение, делится на секции, секция начинается с имени секции в квадратных скобках, комментарии начинаются с символа '#', секции:

svn - клиент командной строки

В качестве первого позиционного параметра клиента командной строки svn указывается действие (команда). Ключи могут использоваться в любом месте командной строки.

Общие ключи svn:

Команды svn (вместо имени файла можно использовать шаблоны в формате fnmatch):

Локальные настройки хранятся в каталоге ~/.subversion (средний приоритет при выборе настроек, создаётся при первом запуске клиента со значениями по умолчанию), общие настройки в каталоге /etc/subversion (наименьший приоритет при выборе настроек) в обычном секционном формате:

Пароли хранятся в каталоге ~/.subversion/auth в открытом виде! Если при сборке svn при запуске configure был указан ключ --with-gnome=keyring, то при запуске клиента svn будет сделана попытка обратиться к gnome-keyring-daemon за хранящимся у него паролем (соответственно д.б. запущен полноценный Gnome и обеспечен доступ к нему). Аккуратная настройка gnome-keyring авторы оставили пользователям в качестве домашнего задания.

Утилита svnversion выводит список ревизий рабочей копии.

Клиенты и прочие дополнения

svnkit - subversion, переписанный на Java.

VisualSVN Server - сборка под MS Windows.

Веб-интерфейс (модули и системы для apache):

Автономные программы:

  • meld - графический diff и merge для Gnome, пакет meld
  • Удаление каталога навсегда

    Поиск "неправильных" файлов:

    svn log -vq путь-к-репозиторию | egrep "^r|\.zip$" | grep -B 1 "\.zip$"
    

    Поиск больших изменений:

    for r in `svn log -q путь-к-репозиторию | grep ^r | cut -d ' ' -f 1 | tr -d r`
    do
       echo "revision $r is " `svn diff путь-к-репозиторию -c $r | wc -c` " bytes";
    done
    

    Изменения

    От 1.5.2 до 1.6.5

    От 1.4.2 до 1.5.2

    Ссылки

    @ Карта сайта News Автора!

    Bog BOS: subversion (svn) - система управления версиями

    Последние изменения:
    2017.04.19: hard: АВР от APC

    TopList

    Copyright © 1996-2017 Sergey E. Bogomolov; www.bog.pp.ru (КГБ знает все, даже то что у Вас на диске ;)