Модели версионирования

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

Проблема разделения файлов

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

Рассматриваемую ситуацию иллюстрирует Рисунок 2.2, «Проблема потери изменений». Допустим у нас есть два со-разработчика Гарри и Салли. Они вдвоем решили одновременно поредактировать один и тот же файл из хранилища. Если первым свои изменения в хранилище сохранит Гарри, то возможно, что (несколькими минутами позже) Салли может непреднамеренно перезаписать их своей новой версией файла. Несмотря на то, что версия файла Гарри не будет полностью потеряна (так как система помнит каждое изменение) внесенные Гарри изменения не будут отражены в новой версии файла Сэлли, потому что, начиная, она, не видела изменения Гарри. Работа Гарри фактически потеряна — или, по крайней мере, отсутствует в последней версии файла — по случайности. Как раз этой ситуации мы и хотим избежать!

Рисунок 2.2. Проблема потери изменений

Проблема потери изменений

Модель Блокирование-Изменение-Разблокирование

Многие системы управления версиями применяют в отношении этой проблемы модель блокирование-изменение-разблокирование. В такой системе хранилище разрешает изменение файла только одному человеку в каждый из моментов времени. До того как Гарри сможет внести изменения он должен «заблокировать» файл. Блокирование файла это как взятие книги в библиотеке; если Гарри заблокировал файл то Салли ни как не сможет его изменить. Хранилище отклонит запрос, если она попытается заблокировать файл. Все что ей остается — это читать файл и ждать когда Гарри закончит свои изменения и снимет блокировку. После того как Гарри разблокирует файл, он возвращает его обратно и теперь Салли может получить его, заблокировать и редактировать. Рисунок 2.3, «Модель блокирование-изменение-разблокирование» демонстрирует эту простую модель.

Рисунок 2.3. Модель блокирование-изменение-разблокирование

Модель блокирование-изменение-разблокирование

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

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

  • Блокирование может вызвать излишнюю пошаговость. Что если Гарри редактирует начало текстового файла, а Салли нужно отредактировать концовку этого же файла? Эти изменения совсем не перекрываются. Они могли бы легко редактировать файл одновременно и никаких особенных проблем это не вызвало бы, предполагая корректное слияние изменений. Блокирование файла в такой ситуации не требуется.

  • Блокирование может вызвать ложное чувство безопасности. Предположим, что Гарри блокирует и редактирует файл А, в то время как Салли одновременно блокирует и редактирует файл В. Но допустим, что А и В зависят друг от друга и сделанные в каждом изменения семантически не совместимы. Неожиданно А и В больше не работают вместе. Блокирующая система бессильна в предотвращении проблемы — вместо этого она обеспечила ложное чувство безопасности. Для Гарри и Салли просто вообразить, что, блокируя файлы каждый начинает безопасную изолированную задачу и не беспокоиться в начале об обсуждении их несовместимых изменений.

Модель Копирование-Изменение-Слияние

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

Вот пример. Скажем и Гарри и Салли создали копированием из хранилища рабочие копии одного и того же проекта. Они работают одновременно и в своих рабочих копиях вносят изменения в один и тот же файл А. Первой свои изменения в хранилище сохраняет Салли. Когда позже Гарри попытается сохранить свои изменения, хранилище проинформирует его о том, что его файл А устарел. Другими словами, файл А каким то образом изменился со времени, когда он его последний раз копировал. Поэтому Гарри просит свой клиент слить любые изменения из хранилища в его рабочую копию файла А. По счастливому совпадению, изменения Салли не перекрываются с его собственными; после объединения обоих наборов изменений он сохраняет свою рабочую копию обратно в хранилище. Рисунок 2.4, «Модель копирование-изменение-слияние» и Рисунок 2.5, «Модель копирование-изменение-слияние (продолжение)» показывают этот процесс.

Рисунок 2.4. Модель копирование-изменение-слияние

Модель копирование-изменение-слияние

Рисунок 2.5. Модель копирование-изменение-слияние (продолжение)

Модель копирование-изменение-слияние (продолжение)

А что если изменения Салли перекрываются с изменениями Гарри? Что тогда? Эта ситуация называется конфликтом и, как правило, это не является большой проблемой. Когда Гарри просит свой клиент слить последние изменения хранилища в рабочую копию, его копия файла А как-то помечается как находящаяся в состоянии конфликта: у него будет возможность видеть оба набора конфликтующих изменений и вручную сделать между ними выбор. Помните, что ПО не может автоматически разрешать конфликты; только человек способен к пониманию и выполнению осмысленного выбора. Разрешив вручную перекрывающиеся изменения - возможно, после обсуждения с Салли — он может безопасно сохранить объединенный файл обратно в хранилище.

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

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