lunedì 14 febbraio 2011

SVN: recuperare dalle versioni precedenti i file rimossi

A volte capita che in un sistema centralizzato come SVN venga "perso" un file, cancellato/rinominato da uno dei committers senza che gli altri se ne rendano conto. Passando il tempo, e accumulandosi le revisioni, diventa sempre piu' difficile trovare un file e visualizzare tutte le modifiche che lo riguardano. Ora, il problema di fatto è uno di quelli che mi ha spinto a lavorare su sistemi decentralizzati (git principalmente e mercurial per alcuni progetti), ma questa è un'altra storia...
Tornando ad SVN, come è possibile risalire all'ultima versione del repository che contiene un determinato file? Ebbene il comando da eseguire è semplice:

svn log -vq | tr -d '\n'| sed -r 's/-{3,}/\n/

Il comando di cui sopra visualizza i numeri di revisione e i percorsi modificati (opzioni -vq) senza il contenuto del testo di messaggio stesso, dopodiché rimuove tutti i fine linea e nuovamente li aggiunge ogni volta che trova una sequenza di piu' di due trattini (le linee di separazione usate nell'output del comando log stesso). I trattini rimossi sono da 3 in su per evitare di essere confusi da firme di mail (solitamente due trattini) o simili, volendo si potrebbe anche aumentare tale valore.
Ebbene tale comando, su un semplice repository di prova, produce un output simile al seguente:

r4 | luca | 2011-02-03 11:46:09 +0000 (Thu, 03 Feb 2011)Changed paths:   A /miao.txt
r3 | luca | 2011-02-03 11:44:09 +0000 (Thu, 03 Feb 2011)Changed paths:   D /ciao.txt
r2 | luca | 2011-02-03 11:43:54 +0000 (Thu, 03 Feb 2011)Changed paths:   M /ciao.txt
r1 | luca | 2011-02-03 11:43:38 +0000 (Thu, 03 Feb 2011)Changed paths:   A /ciao.txt


A questo punto si supponga di voler cercare il file ciao.txt, che esisteva nel repository e che poi è stato cancellato. Diventa immediato eseguire:

svn log -vq | tr -d '\n'| sed -r 's/-{3,}/\n/ | grep ciao.txt

e ottenere di conseguenza:

r3 | luca | 2011-02-03 11:44:09 +0000 (Thu, 03 Feb 2011)Changed paths:   D /ciao.txt
r2 | luca | 2011-02-03 11:43:54 +0000 (Thu, 03 Feb 2011)Changed paths:   M /ciao.txt
r1 | luca | 2011-02-03 11:43:38 +0000 (Thu, 03 Feb 2011)Changed paths:   A /ciao.txt


che corrisponde alla storia del file stesso, con in cima alla lista la cancellazione (D - delete) del file alla revisione r3. E' quindi possibile recuperare il file con:

svn update -r 2 ciao.txt

Da notare che la revisione dalla quale si fa il checkout del file è una in meno rispetto a quella della cancellazione, poiché se si eseguisse l'update alla versione della cancellazione il file risulterebbe ancora cancellato.
In realtà così facendo non si ha la possibilità di reinserire il file nel repository, a meno che non si usino trucchi di ridenominazione a aggiunta. Se quello che si vuole è annullare la cancellazione della revione si deve procedere come segue:

svn merge -c -3  file:///home/luca/tmp/test/

Questa volta il numero di revisione specificato è quello della revisione di cancellazione. Il segno negativo davanti al numero forza il sistema a confrontare le revisioni x e x-1, quindi la 3 e la 2 e ad annullare le modifiche della revisione 3. Occorre specificare il percorso del file del repository dal quale estrarre le versioni, poiché specificando il file stesso si otterrà un errore di file non sotto controllo di versione. Il sistema risponderà con quello che chiama "reverse merge" e il file ricomparirà nella versione corrente pronto per essere nuovamente committato:


--- Reverse-merging r3 into '.':
A    ciao.txt

Nessun commento: