Восстановление удаленных элементов


Отличным свойством системы контроля версия является то, что информация никогда не теряется. При удалении файла или директории, элемент исчезает из правки HEAD но продолжает существовать в более ранних правках. Одним из наиболее частых вопросов, задаваемых новыми пользователями, является такой: «Как мне вернуть назад свой файл или директорию?»

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

Subversion, в отличие от CVS, не имеет директории Attic[16] поэтому для определения необходимой при восстановлении пары координат нужно воспользоваться командой svn log. Лучше всего запустить svn log --verbose в директории, которая содержала удаленный элемент. Параметр --verbose покажет для каждой правки список измененных элементов; все, что вам остается сделать, это найти правку, в которой файл или директория были удалены. Сделать это можно визуально или воспользоваться для обработки вывода каким-то инструментом (grep или может быть последовательным поиском в редакторе).

$ cd parent-dir $ svn log --verbose … ------------------------------------------------------------------------ r808 | joe | 2003-12-26 14:29:40 -0600 (Fri, 26 Dec 2003) | 3 lines Changed paths: D /calc/trunk/real.c M /calc/trunk/integer.c Added fast fourier transform functions to integer.c. Removed real.c because code now in double.c. …

В примере предполагается, что вы ищите удаленный файл real.c. Просмотрев логи родительской директории вы определите, что этот файл был удален в правке 808. Следовательно, последняя существовавшая версия файла была в правке, предшествующей этой. Вывод: необходимо из правки 807 восстановить путь /calc/trunk/real.c.

Поиск был сложной задачей. Теперь, когда известно, что нужно восстановить, есть две возможности.

Одним из вариантов является использование svn merge для применения правки 808 «в обратном направлении». (Как отменять изменения мы уже рассматривали, см. «Отмена изменений».) Это приведет к эффекту повторного добавления фала real.c в виде локальных изменений. Файл будет запланирован для добавления и после фиксации будет опять присутствовать в HEAD.

Однако в этом, отдельно взятом примере, это не самое лучшее решение. Повторное применение правки 808 не только добавит файл real.c; лог сообщение показывает, что будут отменены некоторые изменения в integer.c, чего вы не хотите. Конечно, можно выполнить обратное объединение с правкой 808, а затем отменить (svn revert) локальные изменения integer.c, однако такой подход плохо масштабируется. Что если в правке 808 было изменено 90 файлов?

При втором, более целевом методе, svn merge вообще не используется, а вместо этого применяется команда svn copy. Просто скопируете определенные «парой координат» правку и путь из хранилища в рабочую копию:

$ svn copy --revision 807 \ http://svn.example.com/repos/calc/trunk/real.c ./real.c $ svn status A + real.c $ svn commit -m "Resurrected real.c from revision 807, /calc/trunk/real.c." Adding real.c Transmitting file data . Committed revision 1390.

Знак плюс в статусе показывает, что элемент не просто запланирован для добавления, а запланирован для добавления «с историей». Subversion запоминает откуда он был скопирован. В будущем, запуск svn log для этого файла будет пересекать восстановление файла и всю историю, предшествующую правке 807. Другими словами, новый файл real.c на самом деле не является новым; он является прямым наследником оригинального, удаленного файла.

Хотя наш пример показывает как восстанавливать файл, обратите внимание, на то что этот подход работает также и для восстановления удаленных директорий.



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