Основной задачей системы управления версиями является обеспечение совместного редактирования и использования информации. Однако разные системы используют разные способы для достижения этой цели. Очень важно понимать отличия между этими способами. Во-первых, это поможет сравнить и сопоставить существующие системы управления версиями, в случае, если вы столкнетесь с другими системами, подобными Subversion. Кроме того, впоследствии это поспособствует и более эфективному использованию Subversion, так как эта система поддерживает несколько различных способов работы.
Всем системам управления версиями приходится решать одну и ту же основную проблему: как предоставить пользователям возможность совместного использования информации, при этом не позволяя им наступать друг другу на пятки? Дело в том, что пользователи запросто могут случайно перезаписать в хранилище изменения, сделанные друг другом.
Рассматриваемую ситуацию иллюстрирует Рисунок 1.2, «Проблема потери изменений». Допустим, у нас есть два соразработчика — Гарри и Салли. Каждый из них решил одновременно отредактировать один и тот же файл из хранилища. Если первым свои изменения в хранилище сохранит Гарри, то возможно, что (несколькими минутами позже) Салли может непреднамеренно перезаписать их своей новой версией файла. Несмотря на то, что версия файла Гарри не будет полностью потеряна (так как система помнит каждое изменение), внесенные Гарри изменения не будут отражены в новой версии файла Салли, потому что, начиная, она не видела изменения Гарри. Работа Гарри фактически потеряна — или, по крайней мере, отсутствует в последней версии файла — по случайности. Как раз этой ситуации мы и хотим избежать!
Для того, чтобы несколько авторов не мешало работать друг другу, многие системы управления версиями применяют модель блокирование-изменение-разблокирование. Эта модель запрещает одновременное редактирование файла несколькими пользователями. Эксклюзивность доступа гарантируется блокировками. Перед началом редактирования Гарри должен «заблокировать» файл. Если Гарри заблокирует файл, Салли уже не сможет его заблокировать и внести свои изменения. Ей остается только читать файл и ждать, пока Гарри закончит свои изменения и снимет блокировку. Лишь после того, как Гарри разблокирует файл, Салли сможет получить его, заблокировать и начать редактирование. Рисунок 1.3, «Модель блокирование-изменение-разблокирование» демонстрирует это простое решение.
Проблемой модели блокирование-изменение-разблокирование является то, что она немного ограниченная и часто доставляет неудобства пользователям:
Блокирование может вызвать проблемы администрирования. Иногда Гарри может заблокировать файл, а затем забыть об этом. Между тем, ожидая редактирования файла, у Салли будут связаны руки. А Гарри тем временем уехал в отпуск. Теперь Салли, для снятия блокировки Гарри, нужно обращаться к администратору. Ситуация заканчивается не нужной задержкой и потерянным временем.
Блокирование может вызвать излишнюю пошаговость. Вполне вероятна ситуация, когда Гарри редактирует начало текстового файла, а Салли нужно отредактировать концовку этого же файла? Эти изменения совсем не перекрываются. Они могли бы легко редактировать файл одновременно, и при условии корректного слияния изменений это не вызвало бы никаких особенных проблем. Нет никакой необходимости блокировать файл в такой ситуации.
Блокирование может вызвать ложное чувство безопасности. Предположим, что Гарри блокирует и редактирует файл А, в то время как Салли одновременно блокирует и редактирует файл В. Но допустим, что А и В зависят друг от друга и сделанные в каждом изменения семантически не совместимы. Неожиданно А и В больше не работают вместе. Блокирующая система бессильна в предотвращении проблемы — вместо этого она обеспечила ложное чувство безопасности. Для Гарри и Салли просто вообразить, что, блокируя файлы каждый начинает безопасную изолированную задачу и не беспокоиться об обсуждении их несовместимых изменений заранее. Зачастую, блокирование подменяет настоящее общение.
Subversion, CVS и ряд других систем управления версиями в качестве альтернативы блокированию пользуются моделью копирование-изменение-слияние. В этой модели каждый пользовательский клиент связывается с хранилищем проекта и создает персональную рабочую копию — локальное отражение файлов и каталогов хранилища. После этого пользователи работают одновременно и независимо друг от друга, изменяя свои личные копии. В конце концов, личные копии сливаются в новую, итоговую версию. Обычно система управления версиями помогает в слиянии, но, разумеется, за его корректное выполнение отвечает человек.
В качестве примера предположим, что Гарри и Салли создали рабочие копии одного и того же проекта, скопировав их из хранилища. Они работают одновременно и в своих рабочих копиях вносят изменения в один и тот же файл А. Первой свои изменения в хранилище сохраняет Салли. Когда позже Гарри попытается сохранить свои изменения, хранилище проинформирует его о том, что его файл А устарел. Другими словами, файл А каким то образом изменился со времени, когда он его последний раз копировал. Поэтому Гарри просит свой клиент слить любые изменения из хранилища в его рабочую копию файла А. По счастливому совпадению, изменения Салли не перекрываются с его собственными; после объединения обоих наборов изменений он сохраняет свою рабочую копию обратно в хранилище. Рисунок 1.4, «Модель копирование-изменение-слияние» и Рисунок 1.5, «Модель копирование-изменение-слияние (продолжение)» показывают этот процесс.
А что будет, если изменения Салли перекрывают изменения Гарри? Что тогда? Эта ситуация называется конфликтом и, как правило, это не является большой проблемой. Когда Гарри просит свой клиент слить последние изменения из хранилища в рабочую копию, его копия файла А помечается некоторым образом как находящаяся в состоянии конфликта: у него будет возможность видеть оба набора конфликтующих изменений и вручную сделать между ними выбор. Помните, что ПО не может автоматически разрешать конфликты; только человек способен к пониманию и выполнению осмысленного выбора. Разрешив вручную перекрывающиеся изменения — возможно, после обсуждения с Салли — он может безопасно сохранить объединенный файл обратно в хранилище.
Модель копирование-изменение-слияние может выглядеть немного хаотично, однако, на практике она отлично работает. Пользователи могут работать параллельно, не тратя время на ожидание друг друга. При работе над одними и теми же файлами оказывается, что большинство параллельно вносимых изменений совсем не перекрываются; конфликты бывают редко. И время, которое было потрачено на разрешение конфликтов, как правило, значительно меньше времени, отнимаемого блокирующей системой.
Наконец, все сходится к такому критическому фактору как взаимодействие пользователей. При плохом взаимопонимании увеличивается количество как синтаксических, так и семантических конфликтов. Нет системы, которая может повысить уровень взаимопонимания, и нет системы, которая может определять семантические конфликты. Не стоит возлагать большие надежды на то, что блокирующая система лучше защищена от конфликтов; на практике блокирование снижает продуктивность как ничто другое.