esame della cronologia del file eliminato


160

Se elimino un file in Subversion, come posso vedere la sua cronologia e i suoi contenuti? Se provo a fare svn cato svn logsu un file inesistente, si lamenta che il file non esiste.

Inoltre, se volessi resuscitare il file, dovrei svn addtornare indietro?

(Ho chiesto specificamente di Subversion, ma mi piacerebbe anche sapere come anche Bazaar, Mercurial e Git gestiscono questo caso.)

Risposte:


84

Per ottenere il registro di un file eliminato, utilizzare

svn log -r lastrevisionthefileexisted

Se si desidera resuscitare il file e conservare la cronologia delle versioni, utilizzare

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

Se si desidera solo il contenuto del file ma non verificato (ad es. Per una rapida ispezione), utilizzare

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

In ogni caso, NON usare 'svn up' per recuperare un file cancellato!


2
È inoltre possibile risorgere il file eseguendo un'unione inversa della revisione in cui è stato eliminato. Questa è la procedura consigliata nei documenti SVN. Per quanto riguarda l'utilizzo di "svn up", non è tanto una questione di "non farlo", quanto lo è "non farà ciò che vuoi che faccia".
rmeador,

5
Come posso vedere l'intera cronologia del file, però?
Benjamin Peterson,

71
Semplice: mostra il registro per una cartella principale con l'opzione '-v': otterrai per ogni voce un elenco di percorsi modificati. Trova quello con una 'D' davanti e il nome del tuo file cancellato. Questa è la revisione in cui il file è stato eliminato.
Stefan

8
Questo non sembra funzionare per i file eliminati. Se provo questo, ricevo questo messaggio di errore: 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 'percorso non trovato Vedi la risposta di @Bert Huijben più in basso in questa discussione per una soluzione funzionante.
Keith Palmer Jr.

2
Se ho un repository con 100.000 commit, "lastrevisionthefileexisted" non è facile da trovare!
Jon Watte,

151

Quando vuoi guardare i vecchi file dovresti davvero conoscere la differenza tra:

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

e

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

La prima versione esamina il percorso che è ora disponibile come http: // server / svn / project / file e recupera quel file com'era nella revisione 1234. (Quindi questa sintassi non funziona dopo l'eliminazione di un file).

La seconda sintassi ottiene il file che era disponibile come http: // server / svn / project / file nella revisione 1234. Così questa sintassi FA lavoro su file cancellati.

Puoi anche combinare questi metodi per recuperare un file che era disponibile nella revisione 2345 come http: // server / svn / project / file ma con i contenuti come nel 1234 con:

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

7
Gah, grazie! L'attuale migliore risposta in questo thread non menziona questo, questo è fantastico!
Keith Palmer Jr.

Ciò non è riuscito per me, a meno che non abbia utilizzato percorsi assoluti, poiché il mio client svn locale stava dando un errore quando non era in grado di risolvere ./local/filequando la ./localdirectory non esisteva. Questo potrebbe non essere un problema per le versioni più recenti di SVN.
Derrick Rice,

2
@DerrickRice: in tal caso, la ^notazione è utile: si riferisce alla radice del repository, quindi puoi dire svn cat ^/local/file@REV(a seconda della distanza tra la radice del repository e l'URL).
musiphil,

Questo funziona alla grande in linea di principio. Per le cartelle ricevo quanto segue:svn: E200009: Could not cat all targets because some targets are directories
Barney,

Questa è la risposta migliore Ha anche i voti più alti.
Felipe Alvarez,

94

Innanzitutto, trova il numero di revisione in cui il file è stato eliminato:

svn log -v > log.txt

Quindi cerca log.txt (non un guru SVN, quindi non conosco un modo migliore) per trovare una linea

D <deleted file>

e vedere quale revisione era. Quindi, come nelle altre risposte, resuscitare il file utilizzando la revisione precedente.


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

18
+1 per essere la prima persona a rispondere correttamente alla domanda. Non puoi guardare il contenuto se non conosci la revisione prima che fosse eliminata.
Cerin,

8
@abatishchev questo ottiene l'elenco dei file eliminati, ma scarta le informazioni di revisione, quindi non è utile. Inoltre è lento se stai lavorando con un repository grande / vecchio con molta cronologia delle modifiche.
dal

4
Bene, fantastico con il miglioramento di @ abatishchev. tchen: risolto facilmente usando un argomento -B50 o giù di lì per grep, vedi la mia risposta.
Jonas Byström,

2
Un altro buon modo per limitare l'output di svn log -v per repository molto grandi / vecchi è l'opzione -l. Quindi potresti usare svn log -v -l 100 | grep D "nome.file"
mindmatters

27

Non è niente di particolarmente speciale in Git. Se conosci il nome del file, puoi scoprire la modifica che lo ha rimosso con il registro:

git log -n 1 -- filename

Quindi è possibile utilizzare tale commit per ottenere il file esistente prima dell'eliminazione.

git checkout [last_revision]^ filename

Esempio:

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

Si noti che ciò non ripristina effettivamente il file nel controllo di revisione. Rilascia semplicemente il file così com'era nel suo stato finale nella posizione corrente. È quindi possibile aggiungerlo o semplicemente ispezionarlo o qualsiasi altra cosa da quel punto.


6
Risposta meravigliosa L'unico problema è che la domanda riguarda svn!
JohnK,

16

Una soluzione che utilizza solo la GUI:

Se conosci il nome del file, ma non conosci il suo ultimo numero di revisione o anche il suo percorso:

  1. Da Repo Browser, fai un "Show log" sul root
  2. Premi "Mostra tutto" (nella parte inferiore della finestra di dialogo del registro)
  3. Digita il nome file nella casella di testo Filtro (nella parte superiore della finestra di dialogo del registro)

Questo mostrerà quindi solo quelle revisioni in cui il file è stato aggiunto / modificato / cancellato. Questa è la tua cronologia del file.

Nota che se il file è stato eliminato eliminando una delle sue cartelle principali, non avrà una voce "cancellata" nel registro (e quindi la soluzione di mjy non funzionerà). In questo caso, la sua voce più recente nel registro filtrato corrisponderà al suo contenuto al momento dell'eliminazione.


La forza bruta non è sempre la merda. Soprattutto non su grandi repo.
Jonas Byström,

+1 per una soluzione unica dell'interfaccia utente. La riga di comando è eccezionale, ma non sempre è la risposta migliore senza eccezioni. Soprattutto quando lavori in un ambiente che non controlli e non hai un facile accesso da SVN alla riga di comando.
Mir,

Si noti che la risposta sopra è intesa per la GUI di TortoiseSVN.
Georg Muehlenberg,

13
svn log -v | grep -B50 YourDeletedFileName

Ti fornirà il percorso e la revisione. In git (controlla anche per rinominare):

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

Cosa fa il -B50? Posso ottenere un elenco di file usando svn log e grep abbastanza facilmente usando i suggerimenti qui, ma non riesco a visualizzare facilmente i numeri di revisione, poiché sono visualizzati su una riga diversa. Ho provato la cosa B50 e non mi sembrava che funzionasse così bene per me.
cedd

Emette la linea matematica e le 50 linee sopra che nel caso in cui qualcun altro lo stia leggendo.
cedd

8

Oltre alla risposta di Dustin, se vuoi solo esaminare il contenuto e non verificarlo, nel suo esempio puoi fare:

$ git show 8d4a1f^:slosh.tac

the: separa una revisione e un percorso in quella revisione, chiedendo effettivamente un percorso specifico in una revisione specifica.


Ah, è vero. Lo facevo nel modo più difficile. :)
Dustin,

8

Usa questo comando:

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

Questo elencherà tutte le revisioni che hanno mai cancellato qualsiasi file corrispondente al modello. Cioè, se siete alla ricerca di file README, allora tutti /src/README, /src/README.firste/some/deeply/hidden/directory/READMENOT saranno trovati ed elencati.

Se il tuo nome file contiene barre (percorso), punti o altri caratteri speciali regex, non dimenticare di sfuggirli per evitare errori di corrispondenza o errori.


7

Se non conosci il percorso del file eliminato, risulta che puoi cercarlo nel svn logcomando altrimenti troppo pesante :

svn log --search <deleted_file_or_pattern> -v

Il comando probabilmente sta martellando il server tanto quanto farebbe senza l'opzione di ricerca, ma almeno il resto delle risorse coinvolte (compresi i bulbi oculari) verrebbe in qualche modo sollevato, poiché ciò ti dirà in quale revisione quel file è stato eliminato. Quindi, puoi seguire gli altri suggerimenti (principalmente utilizzando lo stesso svn logcomando, ma già su un percorso definito).


svn log --search _test2.php -v... svn: opzione non valida: --search ... :(
thinsoldier il

5

Il poster ha effettivamente posto 3 domande qui:

  1. Come posso guardare la cronologia di un file eliminato in Subversion?
  2. Come posso guardare il contenuto di un file cancellato in Subversion?
  3. Come posso resuscitare un file cancellato in Subversion?

Tutte le risposte che vedo qui sono per le domande 2 e 3.

La risposta alla domanda 1 è:

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

Devi ancora ottenere il numero di revisione per l'ultima volta in cui il file è esistito, a cui gli altri hanno chiaramente risposto.


4

Ah, da quando sto imparando a usare Bazaar, è qualcosa che ho provato. Senza successo, sembra che non sia possibile registrare e annotare i file rimossi ... :-(

Provato:

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

ma curiosamente (e fortunatamente) posso fare:

> bzr cat -r 3 Stuff/ErrorParser.hta

e:

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

e come suggerito nel bug sopra:

> bzr log -v | grep -B 1 ErrorParser

(regolare il parametro -B( --before-context) secondo necessità).


1

Dovresti specificare una revisione.

svn log -r <revision> <deleted file>

1
Questo dà un errore. Esempio: svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' percorso non trovato
Jeremy

Sei sicuro che esistesse a quella revisione? Devi specificare una revisione in cui il file esisteva effettivamente.
Jack M.

Vedi la risposta di Bert Huijben per la strana differenza tra -r37428 e l'aggiunta di @ 37428 all'URL SVN.
Dubek,

1

Se desideri esaminare la cronologia di un file prima che venga rinominato, come indicato in un commento qui puoi utilizzare

git log --follow -- current_file_name

1

Volevo una risposta, me stesso. Provare quanto segue per produrre solo le eliminazioni 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 } }'

Questo filtra l'output del registro tramite awk . awk buffer ogni riga di revisione che trova, emettendola solo quando viene trovato un record di eliminazione. Ogni revisione viene emessa una sola volta, quindi più eliminazioni in una revisione sono raggruppate insieme (come in standardsvn log nell'output ).

È possibile specificare a --limitper ridurre la quantità di record restituiti. Puoi anche rimuovere il file--stop-on-copy , se necessario.

So che ci sono lamentele sull'efficienza dell'analisi dell'intero registro. Penso che questa sia una soluzione migliore di grep e della sua -Bopzione "cast a wide net" . Non so se sia più efficiente, ma non riesco a pensare a un'alternativa a svn log. È simile alla risposta di @Alexander Amelkin, ma non ha bisogno di un nome specifico. È anche il mio primo script per Awk , quindi potrebbe non essere convenzionale.


1

Supponiamo che il tuo file sia stato chiamato ~ / 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

output di esempio, trovato in 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

copiarlo nella versione precedente (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .

0

Puoi trovare l'ultima revisione che fornisce il file usando la ricerca binaria. Ho creato un semplice /bin/bashscript per questo:

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

Ho scritto uno script php che copia il registro svn di tutti i miei repository in un database mysql. Ora posso fare ricerche di testo completo sui miei commenti o nomi di file.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.