Если я удалю файл в Subversion, как я могу посмотреть его историю и содержимое? Если я пытаюсь выполнить svn cat или svn log с несуществующим файлом, он жалуется, что файл не существует.
Кроме того, если я хочу воскресить файл, нужно ли мне просто вернуть его обратно?
(Я спросил конкретно о Subversion, но я также хотел бы услышать о том, как Bazaar, Mercurial и Git обрабатывают и этот случай.)





Вам нужно будет указать версию.
svn log -r <revision> <deleted file>
Вы уверены, что он существовал в той версии? Вы должны указать ревизию, в которой фактически существовал файл.
См. Ответ Берта Хейбена о странных различиях между -r37428 и добавлением @ 37428 к URL-адресу SVN.
Чтобы получить журнал удаленного файла, используйте
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' для возврата удаленного файла!
Вы также можете восстановить файл, выполнив обратное слияние ревизии, в которой вы его удалили. Это процедура, рекомендованная в документации SVN. Что касается использования «svn up», это не столько вопрос «не делай этого», сколько «он не будет делать то, что вы хотите».
Но как я могу увидеть всю историю файла?
Я бы отредактировал ответ, если бы мог, но так как я не могу, способ получить весь журнал - использовать диапазон ревизий в форме 1: lastrevisionfileexisted (или, возможно, он начинается с нуля ... не могу вспомнить )
Просто: покажите журнал родительской папки с помощью переключателя '-v': для каждой записи вы получите список измененных путей. Найдите файл с буквой D впереди и именем вашего удаленного файла. Это ревизия, из которой был удален файл.
Похоже, это не работает для удаленных файлов. Если я попробую это сделать, я получу следующее сообщение об ошибке: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! Svn / bc / 131 / trunk / include / syeka / poster_funk.inc l.php 'путь не найден См. ответ @Bert Huijben далее в этой ветке для рабочего решения.
Если у меня есть репо со 100 000 коммитов, "lastrevisionthefileexisted" найти нелегко!
Если вы знаете имя файла или его часть, но не помните, когда вы его удалили, вы можете использовать этот быстрый сценарий, который я собрал несколько лет назад: github.com/inquam/svn-find-deleted-file
Сначала найдите номер ревизии, в которой был удален файл:
svn log -v > log.txt
Затем поищите в log.txt (не гуру SVN, поэтому я не знаю лучшего способа) строку с
D <deleted file>
и посмотрите, какая это была ревизия. Затем, как и в других ответах, воскресите файл, используя предыдущую версию.
svn log -v | grep D "имя_файла"
+1 за то, что первым правильно ответил на вопрос. Вы не можете просмотреть содержимое, если не знаете версию до ее удаления.
@abatishchev получает список удаленных файлов, но отбрасывает информацию о ревизии, так что это бесполезно. Также это медленно, если вы работаете с большим / старым репозиторием с большой историей изменений.
Хорошо, отлично с улучшением @abatishchev. tchen: легко исправить с помощью аргумента -B50 или около того для grep, см. мой ответ.
Еще один хороший способ ограничить вывод svn log -v для очень больших / старых репозиториев - это опция -l. Итак, вы можете использовать svn log -v -l 100 | grep D "имя_файла"
В 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 <[email protected]>
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
Обратите внимание, что это фактически не возвращает файл в систему управления версиями. Он просто отбрасывает файл в том виде, в котором он существовал в конечном состоянии, в текущее местоположение. Затем вы можете добавить его или просто проверить, или что-то еще с этого момента.
Замечательный ответ. Проблема только в том, что речь идет о svn!
В дополнение к ответу Дастина, если вы просто хотите изучить содержимое, а не проверять его, в его примере вы можете сделать:
$ git show 8d4a1f^:slosh.tac
: разделяет ревизию и путь в этой ревизии, фактически запрашивая конкретный путь в конкретной ревизии.
Ах, очень верно. Раньше я делал это очень, очень тяжело. :)
Ах, поскольку я учусь использовать Bazaar, я попробовал это. Без успеха, похоже, вы не можете регистрировать и комментировать удаленные файлы в настоящее время ... :-(
Пытался:
> 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)).
Если вы хотите просмотреть старые файлы, вы действительно должны знать разницу между:
svn cat http://server/svn/project/file -r 1234
а также
svn cat http://server/svn/project/file@1234
Первая версия смотрит на путь, который сейчас доступен как http: // сервер / svn / проект / файл, и извлекает этот файл в том виде, в котором он был в редакции 1234. (Таким образом, этот синтаксис выполняет нет после удаления файла).
Второй синтаксис получает файл, который был доступен как http: // сервер / svn / проект / файл в ревизии 1234. Таким образом, этот синтаксис ДЕЛАЕТ работает с удаленными файлами.
Вы даже можете комбинировать эти методы для получения файла, который был доступен в версии 2345 как http: // сервер / svn / проект / файл, но с содержимым, как в 1234, с помощью:
svn cat http://server/svn/project/file@2345 -r 1234
Ага, спасибо! В текущем верхнем ответе в этой ветке об этом не упоминается, это здорово!
Это все еще не помогло мне, если я не использовал абсолютные пути, поскольку мой локальный клиент svn выдавал ошибку, когда не мог разрешить ./local/file, когда каталог ./local не существовал. Это может не быть проблемой для более новых версий SVN.
@DerrickRice: В этом случае пригодится нотация ^: она относится к корню репозитория, поэтому вы можете сказать svn cat ^/local/file@REV (в зависимости от расстояния между корнем репозитория и URL-адресом).
Это в принципе отлично работает. По папкам получаю следующее: svn: E200009: Could not cat all targets because some targets are directories
Это лучший ответ. Также имеет наибольшее количество голосов.
Это тот ответ, который вы ищете. Не уверен, как принятый ответ получил такое количество голосов или был принят, потому что, насколько я могу судить, он не работает.
для оборотов в {900..600}; делать, если svn cat server/repo/file.ext@$rev> / dev / null 2> & 1; затем echo "Последний раз видели на ревизии: $ rev"; перерыв; fi; Выполнено
Решение, использующее только графический интерфейс:
Если вы знаете имя файла, но не знаю его последний номер ревизии или даже его путь:
Затем будут показаны только те ревизии, в которых файл был добавлен / изменен / удален. Это ваша история файла.
Обратите внимание, что если файл был удален путем удаления одной из его родительских папок, у него не будет записи «удалено» в журнале (и поэтому решение mjy не будет работать). В этом случае его самая последняя запись в отфильтрованном журнале будет соответствовать его содержимому при удалении.
Грубая сила - это не всегда дерьмо. Особенно на больших репо.
+1 для решения только для пользовательского интерфейса. Командная строка - это здорово, и все такое, но это не всегда лучший ответ без исключения. Особенно, когда вы работаете в среде, которую не контролируете, и у вас нет простого доступа к SVN из командной строки.
Обратите внимание, что приведенный выше ответ предназначен для графического интерфейса TortoiseSVN.
Если вы хотите просмотреть историю файла до его переименования, то, как указано в комментарий здесь, вы можете использовать
git log --follow -- current_file_name
На самом деле плакат задал здесь 3 вопроса:
Все ответы, которые я вижу здесь, относятся к вопросам 2 и 3.
Ответ на вопрос 1:
svn log http://server/svn/project/file@1234
Вам все равно нужно получить номер редакции, когда последний раз существовал файл, на который здесь четко ответят другие.
Используйте эту команду:
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.
Если ваш имя файла содержит косую черту (путь), точки или другие специальные символы регулярного выражения, не забудьте их экранировать, чтобы избежать несоответствия или ошибок.
svn log -v | grep -B50 YourDeletedFileName
Получу вам путь и доработку. В git (также проверяет переименования):
git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
Что делает -B50? Я могу довольно легко получить список файлов с помощью svn log и grep, используя приведенные здесь советы, но я не могу вообще легко отобразить номера ревизий, поскольку они отображаются в другой строке. Я попробовал B50, и мне показалось, что он не так уж хорош.
Он выводит совпадающую строку и 50 строк выше, на случай, если кто-то еще это прочитает.
Я сам хотел ответа. Попробуйте сделать следующее, чтобы выводить только удаления из 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, так что он может быть нетрадиционным.
Если вы не знаете путь к удаленному файлу, оказывается, вы можете использовать поиск для него в слишком сложной команде svn log:
svn log --search <deleted_file_or_pattern> -v
Команда, вероятно, забивает сервер так же сильно, как и без опции поиска, но, по крайней мере, остальные задействованные ресурсы (включая ваши глазные яблоки) будут немного освобождены, поскольку это скажет вам, в какой ревизии этот файл был удален. Затем вы можете следовать другим советам (в основном, используя ту же команду svn log, но уже по определенному пути).
svn log --search _test2.php -v ... svn: недопустимая опция: --search ... :(
Я написал сценарий php, который копирует журнал svn всех моих репозиториев в базу данных mysql. Теперь я могу выполнять полнотекстовый поиск моих комментариев или имен файлов.
Вы можете найти последнюю ревизию, в которой находится файл, с помощью двоичного поиска.
Для этого я создал простой скрипт /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"
}
Предположим, ваш файл был назван ~ / src / a / b / c / deleted.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 .
Это дает ошибку. Пример: svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' путь не найден