Subversion в действии

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

Вы уже читали о рабочих копиях, сейчас мы покажем, как клиент Subversion их создаёт и использует.

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

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

Рабочая копия содержит несколько дополнительных файлов, созданных и поддерживаемых клиентом Subversion, чтобы помочь ему в работе. Например, ваша рабочая копия содержит подпапку .svn - административную папку рабочей копии. Файлы в этой папке помогают svn-клиенту распознать, какие файлы содержат неопубликованные изменения, а какие устарели. До версии 1.7 Subversion создавал административные папки .svn в каждой подпапке вашей рабочей копии. Subversion 1.7 использует совершенно другой подход. Теперь каждая рабочая копия содержит только одну административную папку в корне рабочей директории.

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

Например, предположим, что у вас есть хранилище с двумя программными проектами.

Рисунок 2.6. Файловая система хранилища

Файловая система хранилища

Другими словами, корневая папка хранилища содержит две папки: paint и calc.

Для получения рабочей копии, вы должны извлечь некоторое поддерево хранилища. (Термин извлечение (check out) по-английски может звучать как что-то, связанное с блокированием или резервированием ресурсов, но это не так: оно просто создаёт для вас личную копию проекта).

Предположим, вы вносите изменения в button.c. Так как в папке .svn запоминается дата модификации файла и исходное содержимое, Subversion может узнать, что вы изменили файл. Однако, Subversion не делает ваши изменения доступными другим, пока вы явно не скажете ей об этом. Действие по опубликованию ваших изменений, обычно известно как фиксация (или внесение) изменений в хранилище.

Для обнародования ваших изменений, вы должны использовать команду Subversion фиксировать (commit).

Теперь ваши изменения в button.c были зафиксированы в хранилище; если другой пользователь извлечёт рабочую копию /calc, он увидит ваши изменения в последней версии файла.

Предположим, вы работаете вместе с Салли, которая извлекла рабочую копию /calc в то же время, что и вы. Когда вы фиксируете ваши изменения в button.c, рабочая копия Салли остаётся неизменной, Subversion изменяет рабочие копии только по запросу пользователя.

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

Обратите внимание, Салли не надо указывать, какие файлы обновлять, Subversion использует информацию в папке .svn, а затем информацию из хранилища, для определения того, какие файлы нуждаются в обновлении.

Адреса URL хранилища

Хранилища Subversion могут быть доступны посредством множества различных методов - с локального диска или через различные сетевые протоколы. Описание расположения хранилища, однако, всегда является разновидностью URL. Схема URL показывает метод доступа:

Таблица 2.1. URL для доступа к хранилищу

СхемаМетод доступа
file:// Прямой доступ к хранилищу на локальном или сетевом диске.
http:// Доступ через протокол WebDAV к Subversion, работающем на сервере Apache.
https:// Тоже самое, что и http://, но с шифрованием SSL
svn:// Не аутентифицируемый TCP/IP доступ через собственный протокол к серверу svnserve.
svn+ssh:// Аутентифицируемый, зашифрованный TCP/IP доступ через собственный протокол к серверу svnserve.

В большинстве случаев, для URL в Subversion используется стандартный синтаксис, позволяющий указывать имя сервера и номер порта в URL. Метод доступа file:// обычно используется для локального доступа, хотя он может быть использован с путями UNC для доступа к узлам по сети. В этом случае URL имеет форму file://имя-компьютера/путь/к/хранилищу. Для локальной машины часть имя-компьютера должна быть либо пропущена, либо указана как localhost. По этой причине, локальные пути обычно указывают с тремя косыми чертами (/), file:///путь/к/хранилищу.

Также, пользователи схемы file:// на платформе Windows вынуждены использовать неофициальный «стандарт» синтаксиса для доступа к хранилищам, находящимся на той же машине, но на дисках, отличных от текущего рабочего диска пользователя. Будет работать любой из двух приведённых ниже синтаксиса путей URL (X обозначает диск, на котором находится хранилище):

file:///X:/path/to/repos
...
file:///X|/path/to/repos
...
      

Обратите внимание, в URL используется обычная (прямая) косая черта, хотя в исходной (не URL) форме путей в Windows используется обратная косая черта.

Вы можете получить доступ к хранилищу FSFS через сетевой ресурс, но это не рекомендовано по разным причинам:

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

  • Не все протоколы для общего доступа к файлам по сети поддерживают блокировку, которую требует Subversion. Однажды вы обнаружите, что ваше хранилище слегка повреждено.

  • Вы должны настроить разрешения на доступ именно так, как нужно. SAMBA особенно сложен в этом отношении.

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

Ревизии

Команда svn commit может опубликовать изменения в любом количестве файлов и папок как одну атомарную транзакцию. В вашей рабочей копии вы можете изменить содержимое файла, создать, удалить, переименовать и скопировать файлы и папки, а затем зафиксировать весь набор изменений как единое целое.

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

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

Удачный способ мысленного представления хранилища - представить его в виде серии деревьев. Вообразите массив номеров ревизий, начинающийся с 0, и растущий слева направо. Под каждым номером ревизии расположено дерево файловой системы, и каждое дерево - это «снимок» состояния хранилища после каждой фиксации.

Рисунок 2.7. Хранилище

Хранилище

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

calc/Makefile:4
integer.c:4
button.c:4
      

На данный момент рабочая папка полностью соответствует ревизии 4 в хранилище. Допустим, что вы внесли изменения в button.c, и зафиксировали эти изменения. При отсутствии других фиксаций ваша фиксация создаст ревизию под номером 5, и теперь ваша рабочая копия выглядит следующим образом:

calc/Makefile:4
integer.c:4
button.c:5
      

Предположим, что после этого Салли фиксирует изменения в integer.c, создавая ревизию 6. Если вы воспользуетесь svn update для приведения своей рабочей копии в актуальное состояние, то она станет выглядеть так:

calc/Makefile:6
integer.c:6
button.c:6
      

Изменения, внесенные Салли в integer.c, будут отражены в вашей рабочей копии, также как и ваши изменения будут присутствовать в button.c. В этом примере текст Makefile в ревизиях 4, 5 и 6 идентичен, однако, Subversion всё равно присваивает файлу Makefile в вашей рабочей копии номер ревизии 6, чтобы показать, что файл в актуальном состоянии. Таким образом, после того как вы выполните полное обновление вашей рабочей копии, она будет соответствовать точно одной ревизии в хранилище.

Как рабочие копии отслеживают хранилище

В служебной папке .svn/ для каждого файла рабочей папки Subversion записывает информацию о двух важнейших свойствах:

  • на какой ревизии основан ваш рабочий файл (это называется рабочая ревизия файла), и

  • дату и время, когда локальная копия последний раз обновлялась из хранилища.

Основываясь на этой информации, и взаимодействуя с хранилищем, Subversion может сказать, в каком из следующих четырех состояний находится рабочий файл:

Не изменялся и не устарел

Файл не изменялся в рабочей папке, и в хранилище не фиксировались изменения этого файла со времени его рабочей ревизии. Команды фиксировать (commit) и обновить (update) ничего делать не будут.

Изменён локально и не устарел

Файл был изменён в рабочей папке, и в хранилище не фиксировались изменения этого файла со времени его базовой ревизии. Существующие локальные изменения не были зафиксированы в хранилище, поэтому команда фиксировать (commit) для файла преуспеет в опубликовании ваших изменений, а команда обновить (update) ничего делать не будет.

Не изменялся и устарел

Файл в рабочей папке не изменялся, но был изменён в хранилище. Со временем, файл должен быть обновлён для соответствия текущей публичной ревизии. Команда фиксировать (commit) ничего делать не будет, а команда обновить (update) внесёт последние изменения в вашу рабочую копию.

Изменён локально и устарел

Файл был изменён как в рабочей папке, так и в хранилище. Команда фиксировать (commit) потерпит неудачу с ошибкой устарел (out-of-date). Файл необходимо сначала обновить; команда обновить (update) попытается объединить опубликованные изменения с локальными. Если Subversion не сможет выполнить объединение в приемлемой форме самостоятельно, то заботу о разрешении конфликта она оставит пользователю.