Untersuchen des Verlaufs der gelöschten Datei


158

Wie kann ich den Verlauf und den Inhalt einer Datei in Subversion anzeigen, wenn ich sie lösche? Wenn ich versuche zu tun , svn catoder svn logauf eine nicht vorhandene Datei, beschwert sich , dass die Datei nicht existiert.

Wenn ich die Datei wiederbeleben wollte, sollte ich sie dann einfach svn addzurückgeben?

(Ich habe speziell nach Subversion gefragt, aber ich würde auch gerne erfahren, wie Bazaar, Mercurial und Git auch mit diesem Fall umgehen.)

Antworten:


85

Verwenden Sie, um das Protokoll einer gelöschten Datei abzurufen

svn log -r lastrevisionthefileexisted

Wenn Sie die Datei wiederbeleben und den Versionsverlauf beibehalten möchten, verwenden Sie

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

Wenn Sie nur den Dateiinhalt möchten, aber nicht versioniert sind (z. B. für eine schnelle Überprüfung), verwenden Sie

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

Verwenden Sie auf keinen Fall 'svn up', um eine gelöschte Datei zurückzubekommen!


2
Sie können die Datei auch wiederbeleben, indem Sie die Revision, in der Sie sie gelöscht haben, in umgekehrter Reihenfolge zusammenführen. Dies ist das in den SVN-Dokumenten empfohlene Verfahren. Bei der Verwendung von "svn up" geht es nicht so sehr um "mach es nicht", sondern darum, "es wird nicht das tun, was du willst".
Rmeador

5
Wie kann ich jedoch den gesamten Verlauf der Datei anzeigen?
Benjamin Peterson

71
Einfach: Zeigen Sie das Protokoll für einen übergeordneten Ordner mit der Option '-v' an. Für jeden Eintrag erhalten Sie eine Liste der geänderten Pfade. Suchen Sie die mit einem 'D' vor und dem Namen Ihrer gelöschten Datei. Das ist die Revision, in der die Datei gelöscht wurde.
Stefan

7
Dies scheint bei gelöschten Dateien nicht zu funktionieren. Wenn ich dies versuche, erhalte ich folgende Fehlermeldung: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! SVv / bc / 131 / trunk / include / syeka / poster_funk.incl.php 'Pfad nicht gefunden Eine funktionierende Lösung finden Sie in der Antwort von @Bert Huijben weiter unten in diesem Thread.
Keith Palmer Jr.

2
Wenn ich ein Repo mit 100.000 Commits habe, ist "lastrevisionthefileexisted" nicht leicht zu finden!
Jon Watte

151

Wenn Sie sich alte Dateien ansehen möchten, sollten Sie wirklich den Unterschied kennen zwischen:

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

und

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

Die erste Version untersucht den Pfad, der jetzt als http: // server / svn / project / file verfügbar ist, und ruft diese Datei wie in Revision 1234 ab. (Diese Syntax funktioniert also nach dem Löschen einer Datei nicht.)

Die zweite Syntax wird die Datei , die als verfügbar war http: // server / svn / Projekt / die Datei in Revision 1234. Also diese Syntax DOES Arbeit auf gelöschte Dateien.

Sie können diese Methoden sogar kombinieren, um eine Datei abzurufen, die in Revision 2345 als http: // server / svn / project / file verfügbar war, aber den Inhalt wie 1234 mit:

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

7
Gah, danke! Die aktuelle Top-Antwort in diesem Thread erwähnt dies nicht, das ist großartig!
Keith Palmer Jr.

Dies schlug für mich immer noch fehl, es sei denn, ich verwendete absolute Pfade, da mein lokaler SVN-Client einen Fehler ausgab, wenn er nicht aufgelöst werden konnte, ./local/filewenn das ./localVerzeichnis nicht vorhanden war. Dies ist möglicherweise kein Problem für neuere Versionen von SVN.
Derrick Rice

2
@DerrickRice: In diesem Fall ist die ^Notation praktisch: Sie bezieht sich auf das Repository-Stammverzeichnis, sodass Sie sagen können svn cat ^/local/file@REV(abhängig von der Entfernung zwischen dem Repository-Stammverzeichnis und der URL).
Musiphil

Das funktioniert im Prinzip super. Für Ordner erhalte ich folgendes:svn: E200009: Could not cat all targets because some targets are directories
Barney

Dies ist die beste Antwort. Hat auch die höchsten Stimmen.
Felipe Alvarez

94

Suchen Sie zunächst die Versionsnummer, unter der die Datei gelöscht wurde:

svn log -v > log.txt

Dann suchen Sie in log.txt (kein SVN-Guru, daher kenne ich keinen besseren Weg) nach einer Zeile mit

D <deleted file>

und sehen, welche Revision das war. Stellen Sie dann wie in den anderen Antworten die Datei mit der vorherigen Version wieder her.


22
svn log -v | grep D "file.name"
abatishchev

18
+1 für die erste Person, die die Frage richtig beantwortet. Sie können den Inhalt nicht anzeigen, wenn Sie die Revision vor dem Löschen nicht kennen.
Cerin

8
@abatishchev Hiermit wird die Liste der gelöschten Dateien abgerufen, die Revisionsinformationen werden jedoch verworfen, sodass dies nicht sinnvoll ist. Es ist auch langsam, wenn Sie mit einem großen / alten Repository mit viel Änderungsverlauf arbeiten.
Tchen

4
Gut, großartig mit der Verbesserung von @ abatishchev. tchen: leicht zu beheben mit einem -B50 oder so Argument zu grep, siehe meine Antwort.
Jonas Byström

2
Eine weitere gute Möglichkeit, die Ausgabe von svn log -v für sehr große / alte Repositorys zu begrenzen, ist die Option -l. Sie können also svn log -v -l 100 | verwenden grep D "file.name"
mindmatters

27

Es ist nichts Besonderes in Git. Wenn Sie den Namen der Datei kennen, können Sie die Änderung, durch die sie entfernt wurde, mit log herausfinden:

git log -n 1 -- filename

Mit diesem Commit können Sie dann die Datei abrufen, wie sie vor dem Löschen vorhanden war.

git checkout [last_revision]^ filename

Beispiel:

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

Beachten Sie, dass dadurch die Datei nicht wieder in die Revisionskontrolle versetzt wird. Die Datei, wie sie im Endzustand vorhanden war, wird einfach am aktuellen Speicherort abgelegt. Sie können es dann hinzufügen oder einfach inspizieren oder was auch immer von diesem Punkt an.


6
Wunderbare Antwort. Das einzige Problem ist, dass die Frage über svn ist!
JohnK

16

Eine Lösung, die nur die GUI verwendet:

Wenn Sie den Namen der Datei kennen, aber nicht die letzte Versionsnummer oder den Pfad kennen:

  1. Führen Sie im Repo-Browser ein "Protokoll anzeigen" im Stammverzeichnis aus
  2. Klicken Sie auf "Alle anzeigen" (am unteren Rand des Protokolldialogs).
  3. Geben Sie den Dateinamen in das Textfeld Filter ein (oben im Protokolldialog).

Dies zeigt dann nur die Revisionen an, bei denen die Datei hinzugefügt / geändert / gelöscht wurde. Dies ist Ihr Verlauf der Datei.

Beachten Sie, dass die Datei, wenn sie durch Löschen eines ihrer übergeordneten Ordner gelöscht wurde, keinen "gelöschten" Eintrag im Protokoll enthält (und daher die Lösung von mjy nicht funktioniert). In diesem Fall entspricht der letzte Eintrag im gefilterten Protokoll dem Inhalt beim Löschen.


Brute Force ist nicht immer die Scheiße. Vor allem nicht auf großen Repos.
Jonas Byström

+1 für eine Lösung nur für die Benutzeroberfläche. Die Befehlszeile ist großartig, aber ausnahmslos nicht immer die beste Antwort. Insbesondere, wenn Sie in einer Umgebung arbeiten, die Sie nicht steuern und keinen einfachen Befehlszeilenzugriff auf SVN haben.
Mir

Bitte beachten Sie, dass die obige Antwort für die TortoiseSVN-Benutzeroberfläche gedacht ist.
Georg Muehlenberg

13
svn log -v | grep -B50 YourDeletedFileName

Wird Ihnen den Weg und die Überarbeitung bringen. In git (prüft auch auf Umbenennungen):

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

Was macht der -B50? Ich kann eine Liste von Dateien mit svn log und grep ganz einfach mit den Tipps hier abrufen, aber ich kann die Revisionsnummern anscheinend nicht so einfach anzeigen, da sie in einer anderen Zeile angezeigt werden. Ich habe das B50-Ding ausprobiert und es schien für mich nicht so erstaunlich zu funktionieren.
Cedd

Es gibt die berechnete Zeile und die 50 Zeilen darüber aus, falls jemand anderes dies liest.
Cedd

8

Zusätzlich zu Dustins Antwort können Sie in seinem Beispiel Folgendes tun, wenn Sie nur den Inhalt untersuchen und nicht überprüfen möchten:

$ git show 8d4a1f^:slosh.tac

Das: trennt eine Revision und einen Pfad in dieser Revision und fragt effektiv nach einem bestimmten Pfad bei einer bestimmten Revision.


Ah, sehr wahr. Früher habe ich das wirklich sehr, sehr schwer gemacht. :)
Dustin

8

Verwenden Sie diesen Befehl:

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

Dadurch werden alle Revisionen aufgelistet, bei denen jemals Dateien gelöscht wurden, die dem Muster entsprechen. Das heißt, wenn Sie auf der Suche nach Datei README, dann alle /src/README, /src/README.firstund /some/deeply/hidden/directory/READMENOTwird gefunden und aufgelistet werden.

Wenn Ihr Dateiname Schrägstriche (Pfad), Punkte oder andere Regex-Sonderzeichen enthält, vergessen Sie nicht, diese zu maskieren, um Fehlanpassungen oder Fehler zu vermeiden.


7

Wenn Sie den Pfad zur gelöschten Datei nicht kennen, können Sie ihn mit dem ansonsten allzu schweren Befehl suchensvn log :

svn log --search <deleted_file_or_pattern> -v

Der Befehl hämmert den Server wahrscheinlich genauso wie ohne die Suchoption, aber zumindest der Rest der beteiligten Ressourcen (einschließlich Ihrer Augäpfel) wäre etwas entlastet, da dies Ihnen sagt, in welcher Revision diese Datei gelöscht wurde. Anschließend können Sie den anderen Tipps folgen (hauptsächlich mit demselben svn logBefehl, jedoch bereits auf einem definierten Pfad).


svn log --search _test2.php -v... svn: ungültige Option: --search ... :(
thinsoldier

5

Das Poster hat hier tatsächlich 3 Fragen gestellt:

  1. Wie sehe ich den Verlauf einer gelöschten Datei in Subversion?
  2. Wie sehe ich den Inhalt einer gelöschten Datei in Subversion?
  3. Wie kann ich eine gelöschte Datei in Subversion wiederbeleben?

Alle Antworten, die ich hier sehe, beziehen sich auf die Fragen 2 und 3.

Die Antwort auf Frage 1 lautet:

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

Sie müssen noch die Revisionsnummer für den Zeitpunkt des letzten Bestehens der Datei abrufen, die hier von anderen eindeutig beantwortet wird.


4

Ah, da ich lerne, Bazaar zu benutzen, habe ich es versucht. Ohne Erfolg können Sie derzeit möglicherweise keine entfernten Dateien protokollieren und mit Anmerkungen versehen ... :-(

Versucht:

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

aber neugierig (und zum Glück) kann ich tun:

> bzr cat -r 3 Stuff/ErrorParser.hta

und:

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

und wie im obigen Fehler vorgeschlagen:

> bzr log -v | grep -B 1 ErrorParser

( Parameter -B( --before-context) nach Bedarf anpassen ).


1

Sie müssten eine Revision angeben.

svn log -r <revision> <deleted file>

1
Dies gibt einen Fehler. Beispiel: svn log -r 37428 svn.example.com/deletedfile.java svn: Pfad '/!svn/bc/98571/deletedfile.java' nicht gefunden
Jeremy

Sind Sie sicher, dass es bei dieser Überarbeitung existiert hat? Sie müssen eine Revision angeben, in der die Datei tatsächlich vorhanden war.
Jack M.

In der Antwort von Bert Huijben finden Sie den seltsamen Unterschied zwischen -r37428 und dem Hinzufügen von @ 37428 zur SVN-URL.
Dubek


1

Ich wollte selbst eine Antwort. Versuchen Sie Folgendes, um nur Löschvorgänge auszugeben 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 } }'

Dies filtert die Protokollausgabe durch awk . awk puffert jede gefundene Revisionszeile und gibt sie nur aus, wenn ein Löschdatensatz gefunden wird. Jede Revision wird nur einmal ausgegeben, sodass mehrere Löschvorgänge in einer Revision zusammengefasst werden (wie bei der Standardausgabe svn log).

Sie können a angeben --limit, um die Anzahl der zurückgegebenen Datensätze zu verringern. Sie können auch die entfernen--stop-on-copy bei Bedarf .

Ich weiß, dass es Beschwerden über die Effizienz des Parsens des gesamten Protokolls gibt. Ich denke, dies ist eine bessere Lösung als grep und die -BOption "Cast a Wide Net" . Ich weiß nicht, ob es effizienter ist, aber ich kann mir keine Alternative dazu vorstellen svn log. Es ähnelt der Antwort von @Alexander Amelkin, benötigt jedoch keinen bestimmten Namen. Es ist auch mein erstes awk- Skript, daher könnte es unkonventionell sein.


1

Angenommen, Ihre Datei wurde als ~ / src / a / b / c / deleted.file bezeichnet

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

Beispielausgabe, fand es bei 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

Kopieren Sie es zurück in die vorherige Version (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .

0

Sie können die letzte Revision finden, die die Datei mithilfe der binären Suche bereitstellt. Ich habe dafür ein einfaches /bin/bashSkript erstellt:

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

Ich habe ein PHP-Skript geschrieben, das das SVN-Protokoll aller meiner Repositorys in eine MySQL-Datenbank kopiert. Ich kann jetzt meine Kommentare oder Dateinamen im Volltext durchsuchen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.