- •Лабораторная работа№4 «Система версионного контроля Subversion»
- •1. Фундаментальные понятия
- •1.1 Хранилище
- •1.2 Модели версионирования
- •1.2.1 Проблема разделения файлов
- •1.2.2 Модель Блокирование-Изменение-Разблокирование
- •1.2.3 Модель Копирование-Изменение-Слияние
- •1.3 Subversion в действии
- •1.3.1 Url хранилища в Subversion
- •1.3.2 Рабочие копии
- •1.3.3 Url хранилища
- •1.3.4 Правки
- •1.3.5 Как рабочие копии отслеживают хранилище
- •1.3.6 Смешивание правок в рабочих копиях
- •1.3.7 Обновления и фиксации отделены друг от друга
- •1.3.8 Смешивание правок
- •2. Импорт
- •2.1 Путешествие во времени вместе с Subversion
- •2.2 Создание рабочей копии
- •2.3 Простейший рабочий цикл
- •2.4 Обновление рабочей копии
- •2.5 Внесение изменений в рабочую копию
- •2.6 Анализ изменений
- •2.6.1 Svn status
- •2.6.3 Svn diff
- •2.6.4 Svn revert
- •2.7 Разрешение конфликтов (при слиянии с чужими изменениями)
- •2.8 Слияние конфликтов вручную
- •2.9 Копирование файла поверх вашего рабочего файла
- •2.10 Использование svn revert
- •2.11 Фиксация изменений
- •2.12 Анализ истории
- •Svn log
- •Svn diff
- •Анализ локальных изменений
- •Сравнение рабочей копии с хранилищем
- •Сравнение хранилища с хранилищем
- •Svn cat
- •Svn list
- •Заключительное слово об истории
- •3. Ветвление и слияние
- •3.1 Что такое ветка?
- •3.2 Использование веток
- •3.3 Создание ветки
- •3.4 Работа с веткой
- •3.5 Ключевые идеи, стоящие за ветками
- •3.6 Копирование изменений между ветками
- •3.7 Копирование отдельных изменений
- •3.8 Ключевые идеи, стоящие за слиянием
- •3.9 Как правильнее всего использовать слияние
- •3.9.1 Ручной контроль слияния
- •3.9.2 Предварительный просмотр результатов слияния
- •3.9.3 Конфликты при слиянии
- •3.9.4 Учитывать или игнорировать происхождение
- •3.10 Типовые примеры
- •3.10.1 Полное объединение двух веток
- •3.10.2 Отмена изменений
- •3.10.3 Восстановление удаленных элементов
- •3.11 Типовые приемы использования веток
- •3.11.1 Ветки релизов
- •3.11.2 Функциональные ветки
- •3.11.3 Переключение рабочей копии
- •3.12 Метки
- •3.12.1 Создание простой метки
- •3.12.2 Создание комплексной метки
- •3.13 Поддержка веток
- •3.13.1 Структура хранилища
- •3.13.2 Продолжительность жизни информации
3.9.2 Предварительный просмотр результатов слияния
Поскольку результатом слияния являются локальные изменения, такая операция не является опасной. Допустив при слиянии ошибку, можно просто отменить изменения (svn revert) и попробовать еще раз.
Однако, возможна ситуация, когда рабочая копия уже содержит локальные изменения. Изменения, примененные при слиянии, будут смешаны с уже существующими, и запуск svn revert нас больше не устроит. Разделить два множества изменений будет невозможно.
В такой ситуации лучше попробовать спрогнозировать или проверить результат слияния до того, как оно произойдет. Проще всего запустить для этого svn diff с теми же аргументами, что и для svn merge. Мы уже показывали это в первом примере объединения. Другим способом предварительного просмотра может служить вызов команды слияния с опцией --dry-run:
$ svn merge --dry-run -r 343:344 http://svn.example.com/repos/calc/trunk
U integer.c
$ svn status
# nothing printed, working copy is still unchanged.
Опция --dry-run позволяет не применять локальные изменения к рабочей копии. Она только показывает статусы, которые имели бы файлы при реальном объединении. Это полезно для получения «сводной» информации о потенциальном слиянии в тех случаях, когда запуск svn diff выдает слишком много подробностей.
3.9.3 Конфликты при слиянии
Так же как и svn update, команда svn merge внедряет изменения в рабочую копию. Следовательно, она тоже может создавать конфликты. Однако конфликты, порождаемые svn merge, имеют определенные отличия, и поэтому мы их сейчас рассмотрим подробнее.
Вначале предположим, что рабочая копия не имеет локальных изменений. При обновлении (svn update) рабочей копии до конкретной правки отправляемые сервером изменения будут всегда «без проблем» внедряться в рабочую копию. Сервер создает дельту, сравнивая два дерева: виртуальный снимок рабочей копии и дерево файлов, которое вас интересует. Учитывая то, что левая часть сравнения полностью эквивалентна тому, что вы уже имеете, дельта гарантированно правильно конвертирует рабочую копию в правую часть сравнения.
Однако svn merge не дает такой гарантии, и может вести себя более непредсказуемо: пользователь может запросить сервер сравнить любые два дерева файлов, даже такие, которые не имеют отношения к рабочей копии! Из этого следует множество потенциальных человеческих ошибок. Иногда пользователи будут сравнивать два ошибочных дерева, создавая дельту, которая не сможет правильно внедриться. svn merge будет пытаться внедрить различия по максимуму, но иногда это будет невозможно. Так же как команда patch в Unix иногда жалуется на «неудачные попытки» объединения, svn merge будет жаловаться на «пропущенные цели»:
$ svn merge -r 1288:1351 http://svn.example.com/repos/branch
U foo.c
U bar.c
Skipped missing target: 'baz.c'
U glub.c
C glorb.h
$
Возможно, что в предыдущем примере файл baz.c существует в обоих сравниваемых снимках ветки и Subversion пытается применить результирующую дельту для того, чтобы изменить содержимое файла, однако в рабочей копии файл отсутствует. В любом случае сообщение «skipped» означает, что скорее всего пользователь ошибся при указании деревьев для сравнения — то есть это классическая ошибка оператора. Если это так, проще всего рекурсивно отменить все изменения, сделанные при слиянии (svn revert --recursive), сразу же после этого удалить все неверсионированные файлы и каталоги и повторно запустить svn merge с другими параметрами.
Обратите внимание на то, что в предыдущем примере в файле glorb.h возник конфликт. Откуда же он мог взяться, если ранее мы договорились, что рабочая копия не имеет локальных изменений? Опять же, пользователь мог запустить svn merge для выделения и применения к рабочей копии какой то старой дельты. В результате такая дельта может содержать изменения, которые нельзя внедрить в рабочий файл без появления проблем, даже если он не имеет локальных изменений.
Еще одно небольшое отличие между svn update и svn merge заключается в названиях файлов, создаваемых при конфликтах. В разделе «Разрешение конфликтов (при слиянии с чужими изменениями)» мы говорили о том, что при обновлении создаются файлы с названиями filename.mine, filename.rOLDREV иfilename.rNEWREV. А svn merge в конфликтной ситуации создает три файла с названиями filename.working, filename.left и filename.right. Термины «left» и«right» указывают здесь на две стороны сравнения, то есть на используемые при сравнении деревья. Это разделение используемых названий поможет вам отличать конфликты, возникшие в результате обновления, от конфликтов, возникших в результате слияния.
