badanie historii usuniętego pliku

159

Jeśli usunę plik w Subversion, jak mogę przejrzeć jego historię i zawartość? Jeśli spróbuję to zrobić svn catlub svn logna nieistniejącym pliku, narzeka, że ​​plik nie istnieje.

Poza tym, jeśli chcę wskrzesić plik, czy powinienem svn addgo po prostu przywrócić?

(Zapytałem konkretnie o Subversion, ale chciałbym również usłyszeć, jak firmy Bazaar, Mercurial i Git radzą sobie również w tej sprawie.)

Benjamin Peterson
źródło

Odpowiedzi:

84

Aby uzyskać dziennik usuniętego pliku, użyj

svn log -r lastrevisionthefileexisted

Jeśli chcesz wskrzesić plik i zachować jego historię wersji, użyj

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

Jeśli chcesz tylko zawartość pliku, ale niewersjonowaną (np. W celu szybkiego sprawdzenia), użyj

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

W każdym razie NIE używaj „svn up”, aby odzyskać usunięty plik!

Stefan
źródło
2
Możesz także przywrócić plik, wykonując odwrotne scalenie wersji, w której został usunięty. Jest to procedura zalecana w dokumentacji SVN. Jeśli chodzi o używanie „svn up”, to nie tyle kwestia „nie rób tego”, ile „nie zrobi tego, co chcesz”.
rmeador
5
Jak mogę jednak zobaczyć całą historię pliku?
Benjamin Peterson
71
Proste: pokaż dziennik folderu nadrzędnego za pomocą przełącznika „-v”: dla każdego wpisu otrzymasz listę zmienionych ścieżek. Znajdź ten z literą „D” na początku i nazwą usuniętego pliku. To jest wersja, w której plik został usunięty.
Stefan
8
Wydaje się, że to nie działa w przypadku usuniętych plików. Jeśli spróbuję, pojawia się ten komunikat o błędzie: 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 'ścieżka nie została znaleziona Zobacz odpowiedź @Bert Huijben w dalszej części tego wątku, aby znaleźć działające rozwiązanie.
Keith Palmer Jr.
2
Jeśli mam repozytorium z 100 000 zatwierdzeń, „ostatnia rewizja istniejącego pliku” nie jest łatwa do znalezienia!
Jon Watte,
151

Jeśli chcesz spojrzeć na stare pliki, naprawdę powinieneś znać różnicę między:

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

i

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

Pierwsza wersja sprawdza ścieżkę, która jest teraz dostępna jako http: // server / svn / project / file i pobiera ten plik tak, jak był w wersji 1234. (Więc ta składnia nie działa po usunięciu pliku).

Druga składnia pobiera plik, który był dostępny jako http: // server / svn / project / file w wersji 1234. Zatem ta składnia DZIAŁA na usuniętych plikach.

Możesz nawet połączyć te metody, aby pobrać plik, który był dostępny w wersji 2345 jako http: // server / svn / project / file, ale z zawartością taką jak w 1234 z:

svn cat http://server/svn/project/file@2345 -r 1234
Bert Huijben
źródło
7
Gah, dzięki! Obecna najlepsza odpowiedź w tym wątku nie wspomina o tym, to świetnie!
Keith Palmer Jr.
Wciąż nie udało mi się to, chyba że użyłem ścieżek bezwzględnych, ponieważ mój lokalny klient svn dawał błąd, gdy nie mógł rozwiązać, ./local/filegdy ./localkatalog nie istniał. Może to nie stanowić problemu w nowszych wersjach SVN.
Derrick Rice
2
@DerrickRice: W takim przypadku ^notacja jest przydatna: odnosi się do katalogu głównego repozytorium, więc możesz powiedzieć svn cat ^/local/file@REV(w zależności od odległości między katalogiem głównym repozytorium a adresem URL).
musiphil
W zasadzie działa to świetnie. W przypadku folderów otrzymuję:svn: E200009: Could not cat all targets because some targets are directories
Barney
To najlepsza odpowiedź. Ma też najwięcej głosów.
Felipe Alvarez
94

Najpierw znajdź numer wersji, w której plik został usunięty:

svn log -v > log.txt

Następnie poszukaj w log.txt (nie guru SVN, więc nie znam lepszego sposobu), aby znaleźć wiersz z rozszerzeniem

D <deleted file>

i zobacz, która to była wersja. Następnie, podobnie jak w przypadku innych odpowiedzi, wskrzesz plik przy użyciu poprzedniej wersji.

mjy
źródło
22
svn log -v | grep D "nazwa.pliku"
abatishchev
18
+1 za bycie pierwszą osobą, która poprawnie odpowiedziała na pytanie. Nie możesz przeglądać zawartości, jeśli nie znasz wersji przed jej usunięciem.
Cerin
8
@abatishchev to uzyskuje listę usuniętych plików, ale odrzuca informacje o wersji, więc nie jest to przydatne. Jest to również powolne, jeśli pracujesz z dużym / starym repozytorium z dużą historią zmian.
tchen
4
Dobrze, świetnie z poprawą @ abatishchev. tchen: łatwo naprawiono za pomocą argumentu -B50 lub czegoś podobnego do grepa, zobacz moją odpowiedź.
Jonas Byström,
2
Innym dobrym sposobem na ograniczenie wyjścia svn log -v dla bardzo dużych / starych repozytoriów jest opcja -l. Więc możesz użyć svn log -v -l 100 | grep D "file.name"
mindmatters
27

W git to nic szczególnego. Jeśli znasz nazwę pliku, możesz sprawdzić zmianę, która go usunęła, w dzienniku:

git log -n 1 -- filename

Następnie możesz użyć tego zatwierdzenia, aby uzyskać plik w takiej postaci, w jakiej istniał przed usunięciem.

git checkout [last_revision]^ filename

Przykład:

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

Należy zauważyć, że w rzeczywistości nie powoduje to przywrócenia pliku do kontroli wersji. Po prostu upuszcza plik, który istniał w swoim ostatecznym stanie, do bieżącej lokalizacji. Następnie możesz go dodać lub po prostu sprawdzić lub cokolwiek od tego momentu.

Dustin
źródło
6
Wspaniała odpowiedź. Jedynym problemem jest to, że pytanie dotyczy svn!
JohnK,
16

Rozwiązanie wykorzystujące tylko GUI:

Jeśli znasz nazwę pliku, ale nie znasz jego numeru ostatniej wersji ani nawet ścieżki:

  1. W przeglądarce repozytorium wykonaj „Pokaż dziennik” w katalogu głównym
  2. Kliknij „Pokaż wszystko” (na dole okna dziennika)
  3. Wpisz nazwę pliku w polu tekstowym Filtr (u góry okna dziennika)

Spowoduje to wyświetlenie tylko tych wersji, w których plik został dodany / zmodyfikowany / usunięty. To jest twoja historia pliku.

Zwróć uwagę, że jeśli plik został usunięty przez usunięcie jednego z jego folderów nadrzędnych, nie będzie miał wpisu „usunięty” w dzienniku (więc rozwiązanie mjy nie będzie działać). W takim przypadku jego najnowszy wpis w przefiltrowanym dzienniku będzie odpowiadał jego zawartości w momencie usunięcia.

Mark Foreman
źródło
Brutalna siła nie zawsze jest gównem. Zwłaszcza nie na dużych repozytoriach.
Jonas Byström,
+1 za rozwiązanie z samym interfejsem użytkownika. Linia poleceń jest świetna i wszystko, ale nie zawsze jest to najlepsza odpowiedź bez wyjątku. Zwłaszcza gdy pracujesz w środowisku, którego nie kontrolujesz i nie masz łatwego dostępu z wiersza poleceń do SVN.
Mir
Zwróć uwagę, że powyższa odpowiedź dotyczy GUI TortoiseSVN.
Georg Muehlenberg
13
svn log -v | grep -B50 YourDeletedFileName

Zapewni ci ścieżkę i rewizję. W git (sprawdza również zmianę nazw):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
Jonas Byström
źródło
Co robi -B50? Mogę łatwo uzyskać listę plików za pomocą svn log i grep, korzystając z poniższych wskazówek, ale nie wydaje mi się, aby wyświetlić numery wersji w prosty sposób, ponieważ są one wyświetlane w innym wierszu. Wypróbowałem B50 i nie wydawało mi się to zadziwiające.
cedd
Wyprowadza matematyczną linię i 50 linii powyżej na wypadek, gdyby ktoś inny to czytał.
cedd
8

Oprócz odpowiedzi Dustina, jeśli chcesz tylko przejrzeć zawartość, a nie to sprawdzić, w jego przykładzie możesz zrobić:

$ git show 8d4a1f^:slosh.tac

the: oddziela wersję i ścieżkę w tej wersji, efektywnie prosząc o określoną ścieżkę przy określonej wersji.

Pieter
źródło
Ach, bardzo prawdziwe. Robiłem to naprawdę, bardzo ciężko. :)
Dustin
8

Użyj tego polecenia:

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

Spowoduje to wyświetlenie wszystkich wersji, które kiedykolwiek usunęły pliki pasujące do wzorca. Oznacza to, że jeśli szukasz pliku README, a następnie wszystko /src/README, /src/README.firsti /some/deeply/hidden/directory/READMENOTbędzie można znaleźć i liście.

Jeśli nazwa pliku zawiera ukośniki (ścieżkę), kropki lub inne specjalne znaki wyrażenia regularnego, nie zapomnij ich zmienić, aby uniknąć niezgodności lub błędów.

Alexander Amelkin
źródło
7

Jeśli nie znasz ścieżki do usuniętego pliku, okazuje się, że możesz go wyszukać za pomocą zbyt ciężkiego svn logpolecenia:

svn log --search <deleted_file_or_pattern> -v

Polecenie prawdopodobnie wbija serwer tak samo jak bez opcji wyszukiwania, ale przynajmniej reszta zaangażowanych zasobów (w tym gałki oczne) byłaby trochę odciążona, ponieważ powie ci, w której wersji ten plik został usunięty. Następnie możesz postępować zgodnie z innymi wskazówkami (głównie za pomocą tego samego svn logpolecenia, ale już na zdefiniowanej ścieżce).

JMB
źródło
svn log --search _test2.php -v... svn: invalid option: --search ... :(
thinsoldier
5

Plakat faktycznie zadał tutaj 3 pytania:

  1. Jak przejrzeć historię usuniętego pliku w Subversion?
  2. Jak przejrzeć zawartość usuniętego pliku w Subversion?
  3. Jak wskrzesić usunięty plik w Subversion?

Wszystkie odpowiedzi, które tu widzę, dotyczą pytań 2 i 3.

Odpowiedź na pytanie 1 brzmi:

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

Nadal musisz uzyskać numer wersji, kiedy plik istniał ostatnio, na co inni wyraźnie udzielają odpowiedzi.

dekeguard
źródło
4

Ach, odkąd uczę się używać Bazaar, próbowałem. Bez powodzenia wygląda na to, że nie możesz obecnie rejestrować i dodawać adnotacji do usuniętych plików ... :-(

Wypróbowany:

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

ale ciekawie (i na szczęście) umiem:

> bzr cat -r 3 Stuff/ErrorParser.hta

i:

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

i jak zasugerowano w powyższym błędzie:

> bzr log -v | grep -B 1 ErrorParser

(ustaw parametr -B( --before-context) w razie potrzeby).

PhiLho
źródło
1

Trzeba by określić wersję.

svn log -r <revision> <deleted file>
Jack M.
źródło
1
To daje błąd. Przykład: svn log -r 37428 svn.example.com/deletedfile.java svn: „/!svn/bc/98571/deletedfile.java” nie znaleziono ścieżki
Jeremy
Czy na pewno istniał w tej wersji? Musisz określić wersję, w której plik faktycznie istniał.
Jack M.
Zobacz odpowiedź Berta Huijbena na temat dziwnej różnicy między -r37428 a dodaniem @ 37428 do adresu URL SVN.
dubek
1

Jeśli chcesz przejrzeć historię pliku przed zmianą jego nazwy, to jak wspomniano w komentarzu , możesz użyć

git log --follow -- current_file_name
Andrew Grimm
źródło
1

Sam chciałem odpowiedzi. Spróbuj wykonać następujące czynności, aby wyprowadzić tylko usunięcia z 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 } }'

To filtruje dane wyjściowe dziennika przez awk . awk buforuje każdy znaleziony wiersz rewizji, wyprowadzając go tylko wtedy, gdy zostanie znaleziony rekord usunięcia. Każda rewizja jest wyprowadzana tylko raz, więc wielokrotne usunięcia w jednej rewizji są grupowane (tak jak w przypadku standardowego svn logwyjścia).

Możesz określić, --limitaby zmniejszyć liczbę zwracanych rekordów. W --stop-on-copyrazie potrzeby możesz również usunąć plik.

Wiem, że pojawiają się skargi dotyczące wydajności analizowania całego dziennika. Myślę, że jest to lepsze rozwiązanie niż grep i jego -Bopcja „rzucić szeroką sieć” . Nie wiem, czy jest bardziej wydajna, ale nie mogę wymyślić alternatywy svn log. Jest podobny do odpowiedzi @Alexander Amelkin, ale nie wymaga konkretnej nazwy. To także mój pierwszy skrypt awk , więc może być niekonwencjonalny.

bratanek
źródło
1

Załóżmy, że twój plik został nazwany ~ / 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

przykładowe dane wyjściowe, znaleziono je pod adresem 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

skopiuj go z powrotem do poprzedniej wersji (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .
Daniel YC Lin
źródło
0

Możesz znaleźć ostatnią wersję, która udostępnia plik, używając wyszukiwania binarnego. Stworzyłem do tego prosty /bin/bashskrypt:

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
źródło
-1

Napisałem skrypt php, który kopiuje dziennik svn wszystkich moich repozytoriów do bazy danych mysql. Mogę teraz wyszukiwać pełnotekstowe komentarze lub nazwy plików.

Thinsoldier
źródło