Мой первый опыт работы с Subversion

5 июля 2011

Я давно знал, что пользоваться системой контроля версий — правильно и полезно. Но все было как-то неохота. Ну вы в курсе, как это бывает. И вот, некоторое время назад, лень удалось побороть. Выбор был сделан в пользу subversion, несмотря на преимущества альтернативных систем. Видимо, чтобы по-настоящему понять преимущества Git/Darcs/Bazaar/Mercurial, нужно какое-то время поработать с SVN. А иначе — с чем сравнивать? К тому же, subversion кажется наиболее «каноничной» системой контроля версий.

1. Настройка subversion и создание первого хранилища

По старой доброй традиции я использовал сервер под управлением FreeBSD :) Устанавливаем subversion:

pkg_add -r subversion

Создаем пользователя svn с группой svn и nologin в качестве оболочки, затем создаем каталог, где будут лежать все репозитории:

adduser
# ...
mkdir /home/svn/repos
chown -R svn:svn /home/svn

Прописываем в /etc/rc.conf:

svnserve_enable="YES"

… и запускаем svnserve:

/usr/local/etc/rc.d/svnserve start

Ура, subversion настроен и запущен! Теперь нужно создать первый репозиторий:

svnadmin create /home/svn/repos/test
cd /home/svn/repos/test/conf
vim svnserve.conf

В svnserve.conf пишем следующее:

[general]
# анонимные пользователи не имеют доступа к репозиторию
# если хотим раздавать исходники всем подряд, меняем на read
anon-access = none
# зайдя по логину-паролю, получаем права на чтение и запись
auth-access = write
# логины и пароли хранятся в файле ./passwd
password-db = passwd
# название репозитория
realm = Test project

Также требуется создать в каталоге conf файл passwd:

[users]
eax = superpuperparol

И — финальный аккорд:

chown -R svn:svn /home/svn

Теперь проверяем все это дело — на этой же машине или на другой:

svn co svn://example.ru/test
cd test

Создаем файл test.pl, пишем в него что-нибудь, затем заливаем в хранилище:

svn add test.pl
svn ci

Оказалось, пользоваться SVN совсем не сложно!

Давайте попробуем еще одну фишку. Наверняка вам часто попадались исходники, содержащие строчку вроде этой:

# $Id: test.pl 10 2011-04-09 09:48:32Z eax $

Если вы хотите, чтобы в вашем коде также содержались имя файла (test.pl), номер ревизии (10), дата-время последнего изменения (2011-04-09 09:48:32Z) и имя пользователя, вносившего последние изменения (eax), просто допишите в комментариях:

 $Id:$

… и выполните команду:

svn -R propset svn:keywords Id ./test

Вся информация будет добавляться в исходники автоматически. Как альтернативный вариант, можно прописать в ~/.subversion/config следующее:

[miscellany]
enable-auto-props = yes
[auto-props]
*.pl = svn:keywords=Id
*.pm = svn:keywords=Id

Тогда не придется вводить команды вручную.

2. Чего не хватает для комфортной работы?

Ничего не имею против VIM, но время от времени я отдаю свое предпочтение Geany. Под Виндой, к примеру, мне удобнее пользоваться им, чем каким-нибудь gvim.exe. Для работы с системами контроля версий в Geany используется плагин GeanyVC. Во FreeBSD можно поставить GeanyVC из портов (в пакеджах его почему-то нет):

portmaster -wd devel/geany-plugins

Активируем плагин в «Инструменты → Менеджер модулей», после чего станут доступны дополнительные пункты меню:

Плагин GeanyVC

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

Инсталлятор для Windows можно скачать отсюда. Только обязательно выберите плагины для вашей версии Geany. Например, плагины для Geany 0.19 могут не заработать с Geany 0.20. Также для работы GeanyVC требуется Win32Svn.

Под Windows есть множество других средств для работы с Subversion, среди которых я бы отметил TortoiseSVN и RapidSVN. Главная фишка TortoiseSVN в том, что он встраивается в контекстное меню explorer.exe. RapidSVN менее удобен, зато является кроссплатформенным (написан на C++ с использованием wxWidgets) и имеет portable версию.

Если вы работаете в системе без прав администратора, то не сможете поставить TortoiseSVN. Кроме того, у меня с ним был странный баг. При слиянии одной из веток проекта с trunk, я получал сообщение «TortoiseSVN: neither the reintegrate source nor target can be the root of the repository», хотя под UNIX обычная команда:

svn merge svn://example.ru/my_project/branches/some_branch

… выполнялась без каких-либо проблем.

3. Subversion и безопасность

К сожалению, svnserve не умеет шифровать трафик. Если вы трудитесь над open source проектом или работаете в интранете (возможно, через VPN), то это и не представляет большой проблемы. Для аутентификации svnserve использует CRAM-MD5, так что пароли перехватить не удастся. Кроме того, вы можете ограничить доступ к репозиторию с помощью фаервола (порт 3690), что обеспечит неплохой уровень безопасности. Правда, все еще остается возможной атака с помощью IP/DNS спуфинга.

Если же шифрование трафика необходимо, subversion предлагает два возможных решения — использовать Apache + mod_dav_svn + SSL или связку SVN + SSH. Сравнение этих решений приведено здесь. Если вас интересует решение на базе Apache, ознакомьтесь с этой статьей. Ниже речь пойдет о настройке SVN + SSH.

Во-первых, svnserve можно прибить, а также удалить svnserve_enable из /etc/rc.conf. Во-вторых, очевидно, нужно запустить sshd (чисто на случай, если вы работаете через telnet :). Затем создаем на сервере учетные записи разработчиков и объединить их в одну группу:

pw usermod eax -G svn

Создаем где-нибудь каталог, куда смогут писать все разработчики:

cd /mnt/projects
mkdir new_project
chown svn:svn new_project
chmod g+rwx new_project

Новое хранилище готово! Никакие дополнительные команды и conf-файлы не нужны. Check-out делается следующей командой:

svn co svn+ssh://eax@example.ru/mnt/projects/new_project

Обратите внимание, что на этот раз нужно задать полный путь к репозиторию. Нас попросят ввести пароль — тот самый, что установлен у пользователя на сервере. Если пароль просят ввести дважды — это нормально, просто используется две ssh-сессии. Во время check-in и update пароль будет запрашиваться только один раз. Чтобы не вводить пароли вовсе, можно воспользоваться identity file.

TortoiseSVN умеет работать с svn+ssh://. Нужен ли ему для этого PuTTy или WinSCP — не знаю, у меня эти утилиты были до установки TortoiseSVN.

В GeanyVC для работы с svn+ssh:// требуется совершить следующую последовательность шагов. Сначала с помощью puttygen.exe создаем пару ключей. Закрытый ключ сохраняем где-нибудь на диске в незашифрованном виде, а открытый ключ дописываем на сервере в ~/.ssh/authorized_keys. Затем в PuTTy сохраняем параметры подключения к svn-серверу, указав в настройках имя пользователя и путь к только что созданному закрытому ключу. Проверяем, удается ли зайти на сервер без ввода пароля. Далее в файле «%APPDATA%/Subversion/config» находим секцию [tunnels] и пишем в ней:

ssh = $SVN_SSH "C:/Program Files (x86)/PuTTY/plink.exe"

Пробуем сделать check-out в cmd.exe:

svn co svn+ssh://PUTTY_SESSION_NAME/mnt/projects/new_project

Правим код в Geany, пробуем сделать commit. Кстати, утверждается, что подобная последовательность действий работает и для RapidSVN.

4. Настраиваем ночные сборки

Ночные сборки обладают массой полезных свойств и реализуются довольно просто. Вот пример скрипта, который делает check-out проекта, прогоняет тесты и, в случае обнаружения ошибок, высылает отчет на заданный e-mail:

#!/usr/bin/perl

# mojo-test.pl script v 0.1
# (c) Alexandr A Alexeev 2011 | http://eax.me/

use strict;

## config ##
my $svn_user = 'eax';
my $svn_host = 'example.ru';
my $project_name = 'new_project';
my $project_path = ' mnt/projects';
my $report_email = 'eax@example.ru';
#############

# делаем check-out проекта (не забыть про identity file!)
my $cmd = "svn co svn+ssh://$svn_user@".
  "$svn_host/$project_path/$project_name/ ./project";
`$cmd`;
if($?) {
  $cmd = "echo '' | ".
    "mail -s 'Failed to check-out $project_name! Error: $?'".
    " $report_email";
  `$cmd`;
  exit 1;
}

# прогоняем тесты
`perl ./project/script/$project_name test > ./t.txt`;
if($?) {
  `cat t.txt | mail -s 'Test of $project_name' $report_email`;
}

# подчищаем за собой
`rm -rf ./project/ && rm ./t.txt`;

Только не забудьте про crontab и identity file. Предполагается, что проект разрабатывается на базе Mojolicious, но, очевидно, аналогичный скрипт несложно написать и для проекта на C++, в котором используется CppUnit.

5. Что мы получаем в итоге?

А получаем мы следующее:

  • Весь код автоматически бэкапится на сервере. Плюс несложно настроить резервное копирование с svn-сервера еще куда-нибудь;
  • Мы всегда можем вернуться к одной из предыдущих версий (ревизий) любого файла. Вам приходилось когда-нибудь комментировать куски кода на случай, если вдруг сделанные вами изменения окажутся неверными? Так вот, больше так делать не нужно;
  • Удобная работа в команде, вплоть до одновременного редактирования одного файла несколькими людьми. Даже если вы — единственный программист в команде, как минимум, теперь вы можете переложить какую-нибудь верстку на другого человека;
  • Шифрование трафика;
  • Проще настроить ночные сборки;

Ну вот, кажется, и все, что я хотел рассказать. Как обычно, любые комментарии и вопросы приветствуются.

Дополнение: В продолжение темы — Краткая шпаргалка по основным командам Subversion и Моя шпаргалка по работе с Git.

Метки: .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.