просмотр истории удаленного файла

160

Если я удаляю файл в Subversion, как я могу посмотреть его историю и содержимое? Если я попытаюсь сделатьsvn cat или svn logна несуществующий файл, он жалуется, что файл не существует.

Кроме того, если я хочу воскресить файл, я должен просто svn add вернуть его?

(Я спрашивал конкретно о Subversion, но я также хотел бы услышать о том, как Bazaar, Mercurial и Git также занимаются этим делом.)

Бенджамин Петерсон
источник

Ответы:

84

Чтобы получить журнал удаленного файла, используйте

svn log -r lastrevisionthefileexisted

Если вы хотите воскресить файл и сохранить его историю версий, используйте

svn copy url/of/file@lastrevisionthefileexisted -r lastrevisionthefileexisted path/to/workingcopy/file

Если вы просто хотите содержимое файла, но не версионно (например, для быстрой проверки), используйте

svn cat url/of/file@lastrevisionthefileexisted -r latrevisionthefileexisted > file

В любом случае, НЕ используйте 'svn up', чтобы вернуть удаленный файл!

Стефан
источник
2
Вы также можете повторно воскресить файл, выполнив обратное объединение ревизии, в которой вы его удалили. Эта процедура рекомендуется в документации SVN. Что касается использования «svn up», это не столько вопрос «не делай этого», сколько «он не будет делать то, что ты хочешь».
rmeador
5
Как я могу увидеть всю историю файла?
Бенджамин Петерсон
71
Просто: покажите журнал для родительской папки с ключом -v: для каждой записи вы получите список измененных путей. Найдите файл с буквой «D» и названием вашего удаленного файла. Это ревизия, где файл был удален.
Стефан,
8
Кажется, это не работает для удаленных файлов. Если я попробую это, я получу это сообщение об ошибке: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! Svn / bc / 131 / trunk / include / syeka / poster_funk.incl.php 'путь не найден. См. ответ @Bert Huijben ниже по этой теме для рабочего решения.
Кит Палмер младший
2
Если у меня есть репо с 100 000 коммитов, «lastrevisionthefileexisted» найти нелегко!
Джон Уотт
151

Когда вы хотите посмотреть на старые файлы, вы действительно должны знать разницу между:

svn cat http://server/svn/project/file -r 1234

и

svn cat http://server/svn/project/file@1234

Первая версия просматривает путь, который теперь доступен как http: // server / svn / project / file, и получает этот файл, как это было в ревизии 1234. (Таким образом, этот синтаксис не работает после удаления файла).

Второй синтаксис получает файл , который был доступен в качестве HTTP: // сервера / SVN / проект / файл в пересмотре 1234. Так что этот синтаксис ДЕЛАЕТ работу на удаленные файлы.

Вы можете даже объединить эти методы для получения файла, который был доступен в ревизии 2345, как http: // server / svn / project / file, но с содержимым, как это было в 1234, с:

svn cat http://server/svn/project/file@2345 -r 1234
Берт Хуйбен
источник
7
Гах, спасибо! Текущий топ-ответ в этой теме не упоминает об этом, это здорово!
Кит Палмер младший
Это все равно не помогло, если я не использовал абсолютные пути, так как мой локальный svn-клиент выдавал ошибку, когда не удалось разрешить, ./local/fileкогда ./localкаталог не существовал. Это не может быть проблемой для более новых версий SVN.
Деррик Райс
2
@DerrickRice: в этом случае ^нотация оказывается полезной: можно сказать, что это относится к корню хранилища svn cat ^/local/file@REV(в зависимости от расстояния между корнем хранилища и URL).
Musiphil
Это прекрасно работает в принципе. Для папок я получаю следующее:svn: E200009: Could not cat all targets because some targets are directories
Барни
Это лучший ответ. Имеет также самые высокие голоса.
Фелипе Альварес
94

Сначала найдите номер ревизии, в которой был удален файл:

svn log -v > log.txt

Затем найдите в файле log.txt (не гуру SVN, так что я не знаю лучшего способа) строку с

D <deleted file>

и посмотрите, какая ревизия была. Затем, как и в других ответах, воскресите файл, используя предыдущую версию.

мЯн
источник
22
svn log -v | grep D "file.name"
абатищев
18
+1 за то, что был первым, кто правильно ответил на вопрос. Вы не можете просмотреть содержимое, если не знаете ревизию до ее удаления.
Церин
8
@abatishchev это получает список удаленных файлов, но отбрасывает информацию о ревизии, так что это бесполезно. Также это медленно, если вы работаете с большим / старым репозиторием с большой историей изменений.
tchen
4
Хорошо, отлично с улучшением @ abatishchev. tchen: легко исправить с помощью аргумента -B50 или около того, см. мой ответ.
Йонас Быстрём
2
Другим хорошим способом ограничения вывода svn log -v для очень больших / старых репозиториев является опция -l. Таким образом, вы можете использовать svn log -v -l 100 | grep D "file.name"
mindmatters
27

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

git log -n 1 -- filename

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

git checkout [last_revision]^ filename

Пример:

dhcp-120:/tmp/slosh 587% ls -l slosh.tac
ls: slosh.tac: No such file or directory
dhcp-120:/tmp/slosh 588% git log -n 1 -- slosh.tac
commit 8d4a1f1a94e4aa37c1cb9d329a140d08eec1b587
Author: Dustin Sallings <dustin@spy.net>
Date:   Mon Dec 15 11:25:00 2008 -0800

    Get rid of a .conf and replace it with .tac.
dhcp-120:/tmp/slosh 589% git checkout 8d4a1f^ slosh.tac
dhcp-120:/tmp/slosh 590% ll slosh.tac
-rw-------  1 dustin  wheel  822 Dec 30 12:52 slosh.tac

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

Dustin
источник
6
Прекрасный ответ. Единственная проблема в том, что речь идет о SVN!
JohnK
16

Решение с использованием только графического интерфейса:

Если вы знаете имя файла, но не знаете его номер последней редакции или даже путь к нему:

  1. Из Repo Browser сделать «Показать журнал» в корне
  2. Нажмите «Показать все» (внизу диалогового окна журнала)
  3. Введите имя файла в текстовое поле «Фильтр» (вверху диалога журнала)

Это тогда покажет только те ревизии, где файл был добавлен / изменен / удален. Это ваша история файла.

Обратите внимание, что если файл был удален путем удаления одной из его родительских папок, у него не будет «удаленной» записи в журнале (и поэтому решение mjy не будет работать). В этом случае его последняя запись в отфильтрованном журнале будет соответствовать его содержимому при удалении.

Марк Форман
источник
Грубая сила не всегда дерьмо. Особенно не на больших репо.
Йонас Быстрём
+1 для решения только для пользовательского интерфейса. Командная строка отличная, и все, но это не всегда лучший ответ без исключения. Особенно, когда вы работаете в среде, которую вы не контролируете, и у вас нет простого доступа командной строки к SVN.
Мир
Обратите внимание, что приведенный выше ответ предназначен для графического интерфейса TortoiseSVN.
Георг
13
svn log -v | grep -B50 YourDeletedFileName

Получит вам путь и ревизию. В git (также проверяет переименования):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
Йонас Быстрём
источник
Что делает -B50? Я могу легко получить список файлов, используя svn log и grep, используя подсказки, приведенные здесь, но я не могу с легкостью отобразить номера ревизий так, как они отображаются в другой строке. Я попробовал B50, и мне это показалось не таким уж удивительным.
Cedd
Он выводит математическую строку и 50 строк выше, если кто-то еще читает это.
Cedd
8

В дополнение к ответу Дастина, если вы просто хотите изучить содержимое, а не проверить его, в его примере вы можете сделать:

$ git show 8d4a1f^:slosh.tac

: разделяет ревизию и путь в этой ревизии, фактически запрашивая конкретный путь в конкретной ревизии.

Pieter
источник
Ах, очень верно. Раньше я делал это очень, очень сложно. :)
Дастин
8

Используйте эту команду:

svn log -v | awk '/^r[0-9]+/ { rev = $1; }; / D .*filename_escaped_for_regex/ { print rev" "$2; };'

Это перечислит все ревизии, которые когда-либо удаляли любые файлы, соответствующие шаблону. То есть, если вы ищете файл README, то все /src/README,/src/README.first и /some/deeply/hidden/directory/READMENOTбудут найдены и перечислены.

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

Александр Амелькин
источник
7

Если вы не знаете путь к удаленному файлу, оказывается, что вы можете искать его с помощью команды, которая в противном случае будет слишком тяжелой svn log:

svn log --search <deleted_file_or_pattern> -v

Команда, вероятно, забивает сервер так же сильно, как и без опции поиска, но, по крайней мере, остальные задействованные ресурсы (включая ваши глазные яблоки) будут немного облегчены, поскольку это скажет вам, в какой ревизии этот файл был удален. Затем вы можете следовать другим советам (в основном используя ту же svn logкоманду, но уже по заданному пути).

JMB
источник
svn log --search _test2.php -v... svn: неверный параметр: --search ... :(
thinsoldier
5

Постер фактически задал 3 вопроса здесь:

  1. Как посмотреть историю удаленных файлов в Subversion?
  2. Как посмотреть содержимое удаленного файла в Subversion?
  3. Как воскресить удаленный файл в Subversion?

Все ответы, которые я вижу здесь, на вопросы 2 и 3.

Ответ на вопрос 1:

svn log http://server/svn/project/file@1234

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

dekeguard
источник
4

Ах, поскольку я учусь пользоваться Базаром, я попробовал это. Без успеха, кажется, вы не можете войти и аннотировать удаленные файлы настоящее время ... :-(

Пытался:

> bzr log -r 3 Stuff/ErrorParser.hta
bzr: ERROR: Path does not have any revision history: Stuff/ErrorParser.hta

но с любопытством (и к счастью) я могу сделать:

> bzr cat -r 3 Stuff/ErrorParser.hta

и:

> bzr diff -r 2..3 Stuff/ErrorParser.hta

и как предложено в ошибке выше:

> bzr log -v | grep -B 1 ErrorParser

(отрегулируйте -B( --before-context) параметр по мере необходимости).

PhiLho
источник
1

Вам нужно будет указать ревизию.

svn log -r <revision> <deleted file>
Джек М.
источник
1
Это дает ошибку. Пример: svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' путь не найден
Джереми
Вы уверены, что он существовал на этой ревизии? Вы должны указать ревизию, где файл действительно существовал.
Джек М.
См. Ответ Берта Хейббена о странных различиях между -r37428 и добавлением @ 37428 к URL-адресу SVN.
Дубек
1

Если вы хотите просмотреть историю файла до того, как он будет переименован, то, как указано в комментарии, вы можете использовать

git log --follow -- current_file_name
Эндрю Гримм
источник
1

Я сам хотел получить ответ. Попробуйте следующее для вывода только удаляет из svn log.

svn log --stop-on-copy --verbose [--limit <limit>] <repo Url> | \
awk '{ if ($0 ~ /^r[0-9]+/) rev = $0 }
  { if ($0 ~ /^ D /) { if (rev != "") { print rev; rev = "" }; print $0 } }'

Это фильтрует вывод журнала через awk . awk буферизует каждую найденную строку ревизии, выводя ее только тогда, когда найдена удаляемая запись. Каждая ревизия выводится только один раз, поэтому несколько удалений в ревизии группируются (как в стандартном варианте).svn log выводе).

Вы можете указать, --limitчтобы уменьшить количество возвращаемых записей. Вы также можете удалить--stop-on-copy , по мере необходимости.

Я знаю, что есть жалобы на эффективность разбора всего журнала. Я думаю, что это лучшее решение, чем grep и его -Bопция «бросить широкую сеть» . Я не знаю, является ли это более эффективным, но я не могу придумать альтернативу svn log. Это похоже на ответ @Alexander Amelkin, но не требует конкретного имени. Это также мой первый скрипт на awk , поэтому он может быть нетрадиционным.

nshew
источник
1

Предположим, что ваш файл был назван как ~ / src / a / b / c / dele.file

cd ~/src/a/b/c  # to the directory where you do the svn rm or svn mv command
#cd ~/src   # if you forget the correct directory, just to the root of repository
svn log -v | grep -w -B 9 deleted.file | head  # head show first 10 lines

образец вывода, нашел его на r90440

...
r90440 | user | 2017-02-03 11:55:09 +0800 (Fri, 03 Feb 2017) | 4 lines
Changed paths:
  M /src/a/b/c/foo
  M /src/a/b/c/bar
  D /src/a/b/c/deleted.file

скопируйте его обратно в предыдущую версию (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .
Даниэль YC Лин
источник
0

Вы можете найти последнюю ревизию, которая предоставляет файл, используя бинарный поиск. Я создал простой /bin/bashскрипт для этого:

function svnFindLast(){
 # The URL of the file to be found
 local URL="$1"
 # The SVN revision number which the file appears in (any rev where the file DOES exist)
 local r="$2"
 local R
 for i in $(seq 1 "${#URL}")
  do
   echo "checkingURL:'${URL:0:$i}'" >&2
   R="$(svn info --show-item revision "${URL:0:$i}" 2>/dev/null)"
   echo "R=$R" >&2
   [ -z "$R" ] || break
 done
 [ "$R" ] || {
  echo "It seems '$URL' is not in a valid SVN repository!" >&2
  return -1
 }
 while [ "$r" -ne "$R" -a "$(($r + 1))" -ne "$R" ]
 do
  T="$(($(($R + $r)) / 2))"
  if svn log "${URL}@${T}" >/dev/null 2>&1
   then
    r="$T"
    echo "r=$r" >&2
   else
    R="$T"
    echo "R=$R" >&2
  fi
 done
 echo "$r"
}
Sebo.PL
источник
-1

Я написал php-скрипт, который копирует журнал svn всех моих репозиториев в базу данных mysql. Теперь я могу выполнять полнотекстовый поиск по моим комментариям или именам файлов.

thinsoldier
источник