Конфликты при объединении


Так же как и команда 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» указывают на две стороны сравнения, то есть на используемые при сравнении деревья. Это разделение используемых названий поможет вам отличать конфликты возникшие в результате обновления от конфликтов, возникших в результате объединения.



Содержание раздела