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

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

Проблема совместного использования файлов

Предположим такую ситуацию: в компании есть два сотрудника, работающие над одним проектом: Игорь и Света. Они одновременно решили поправить один и тот же файл. Если Игорь сохранит свои изменения первым, тогда Света (сохранившись несколькими секундами позже) может непреднамеренно их переписать своей новой версией файла. Несмотря на то, что версия Игоря не будет потеряна навсегда (потому что система запоминает все изменения), внесённых Игорем правок не будет в новой версии файла Светы, ведь она их никогда не видела. Работа Игоря фактически потеряна - или, по крайней мере, отсутствует в последней версии файла. А это как раз то, чего мы хотим избежать!

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

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

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

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

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

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

Проблема с моделью блокирование-изменение-разблокирование в ее жестокости, она может создать следующие неудобства пользователям:

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

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

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

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

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

Вот пример: Игорь и Света создали свои рабочие копии одного и того же проекта. Они работают одновременно, и вносят изменения в файл A в своих рабочих копиях. Света первой сохраняет свои изменения в хранилище. Затем, когда Игорь пытается сохранить свои, хранилище информирует его, что его файл А устарел. Другими словами, файл А в хранилище был изменён с тех пор, как Игорь получил его. Тогда Игорь выполняет слияние (merge) любых изменений хранилища со своей рабочей копией. Вероятно, что изменения Светы не пересекаются с его собственными, и, поскольку теперь его рабочая копия содержит оба набора изменений, он записывает её обратно в хранилище.

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

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

Рисунок 2.5. ...Копирование-Изменение-Слияние. Продолжение

...Копирование-Изменение-Слияние. Продолжение

Но что будет, если изменения Светы всё-таки пересекаются с изменениями Игоря? Что происходит в этом случае? Эта ситуация, называемая конфликтом, обычно не такая уж большая проблема. Когда Игорь просит объединить свои изменения с изменениями из хранилища, его копия файла А помечается как находящаяся в состоянии конфликта: он видит оба набора конфликтующих изменений, и вручную выбирает между ними. Обратите внимание, программа не может автоматически разрешать конфликты, только человек способен понять и сделать необходимый осмысленный выбор. Когда Игорь разрешит пересекающиеся изменения (возможно, путём обсуждения со Светой!), он может безопасно сохранить объединённый файл обратно в хранилище.

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

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

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

Что же делает Subversion?

По умолчанию Subversion использует модель копирование-изменение-слияние, и в большинстве случаев это всё, что вам нужно. Однако, начиная с версии 1.2, Subversion также поддерживает блокирование файлов, так что если у вас есть необъединяемые файлы, или если руководство просто вынудило вас работать в режиме с блокировками, Subversion предоставляет вам такую возможность.