вивчення історії видаленого файлу


159

Якщо я видаляю файл у програмі 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 / включати / 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 або близько того, щоб отримати греп, див. мою відповідь.
Jonas Byström

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

Зауважте, що це насправді не повертає файл до контролю версій. Він просто перекидає файл, який існував у його остаточному стані, у поточне місце. Потім ви можете додати його або просто оглянути його або що-небудь ще з цього пункту.


6
Чудова відповідь. Проблема лише в тому, що питання стосується svn!
ДжонК

16

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

Якщо ви знаєте ім'я файлу, але не знаєте його останній номер редакції чи навіть його шлях:

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

Після цього відображатимуться лише ті версії, де файл був доданий / модифікований / видалений. Це ваша історія файлу.

Зауважте, що якщо файл було видалено, видаливши одну з його батьківських папок, у ньому не буде запису "видалений" у журналі (і тому рішення mjy не працюватиме). У цьому випадку його остання запис у відфільтрованому журналі буде відповідати його вмісту при видаленні.


Брутальна сила - це не завжди лайно. Особливо не на великих репостах.
Jonas Byström

+1 для рішення лише у користувальницькому інтерфейсі. Командний рядок - це чудово, і все, але це не завжди найкраща відповідь без винятку. Особливо, коли ви працюєте в середовищі, яке ви не контролюєте, і не маєте легкого доступу до SVN командного рядка.
Мир

Зауважте, що вищевказана відповідь призначена для графічного інтерфейсу TortoiseSVN.
Георг

13
svn log -v | grep -B50 YourDeletedFileName

Ви отримаєте вам шлях та доопрацювання. У git (також перевіряє на перейменування):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName

Що робить -B50? Я можу отримати список файлів, використовуючи журнал svn і grep, досить легко, використовуючи поради тут, але я не можу легко переглянути ревізійні номери, оскільки вони відображаються в іншому рядку. Я спробував B50 річ, і це, здається, не працює так дивно для мене.
cedd

Він виводить математичну лінію і на 50 рядків вище, якщо у випадку, якщо хтось читає це.
cedd

8

Окрім відповіді Дастіна, якщо ви просто хочете вивчити вміст, а не перевірити його, у його прикладі ви можете зробити:

$ git show 8d4a1f^:slosh.tac

the: відокремлює ревізію та шлях у цій редакції, фактично запитуючи певний шлях під час конкретної редакції.


Ах, дуже правда. Я звик робити це справді, дуже важко. :)
Дастін

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команду, але вже на визначеному шляху).


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

Ще потрібно отримати номер редакції, коли останній файл існував, на що тут чітко відповідають інші.


4

Ах, оскільки я вчусь користуватися 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) параметр за потребою).


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 до SVN URL.
дубек


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висновку).

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

Я знаю, є скарги на ефективність розбору всього журналу. Я думаю, що це краще рішення, ніж греп та його -Bваріант "кинути широку мережу" . Я не знаю, чи це більш ефективно, але я не можу придумати альтернативу svn log. Це схоже на відповідь @Alexander Amelkin, але не потребує конкретного імені. Це також мій перший сценарій awk , тому це може бути нетрадиційно.


1

Припустимо, ваш файл був названий як ~ / src / a / b / c / delete.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 .

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"
}

-1

Я написав скрипт php, який копіює журнал svn всіх моїх сховищ у базу даних mysql. Тепер я можу робити повнотекстовий пошук моїх коментарів чи імен файлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.