examinar el historial del archivo eliminado

160

Si elimino un archivo en Subversion, ¿cómo puedo ver su historial y contenido? Si intento hacer svn cato svn logen un archivo inexistente, se queja de que el archivo no existe.

Además, si quisiera resucitar el archivo, ¿debería svn adddevolverlo?

(Pregunté específicamente sobre Subversion, pero también me gustaría saber cómo Bazaar, Mercurial y Git manejan este caso también).

Benjamin Peterson
fuente

Respuestas:

84

Para obtener el registro de un archivo eliminado, use

svn log -r lastrevisionthefileexisted

Si desea resucitar el archivo y mantener su historial de versiones, use

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

Si solo desea el contenido del archivo pero no versionado (por ejemplo, para una inspección rápida), use

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

En cualquier caso, ¡NO use 'svn up' para recuperar un archivo eliminado!

Stefan
fuente
2
También puede resucitar el archivo haciendo una fusión inversa de la revisión en la que lo eliminó. Este es el procedimiento recomendado en los documentos SVN. En cuanto al uso de "svn up", no se trata tanto de "no lo hagas" como de "no hará lo que quieres que haga".
rmeador
55
Sin embargo, ¿cómo puedo ver el historial completo del archivo?
Benjamin Peterson
71
Simple: muestre el registro de una carpeta principal con el interruptor '-v': obtendrá para cada entrada una lista de rutas cambiadas. Encuentra el que tiene una 'D' delante y el nombre de tu archivo eliminado. Esa es la revisión donde se eliminó el archivo.
Stefan
8
Esto no parece funcionar para archivos eliminados. Si intento esto, recibo este mensaje de error: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! Svn / bc / 131 / trunk / incluir / syeka / poster_funk.incl.php 'ruta no encontrada Ver la respuesta de @Bert Huijben más abajo en este hilo para una solución de trabajo.
Keith Palmer Jr.
2
Si tengo un repositorio con 100,000 commits, ¡"lastrevisionthefileexisted" no es fácil de encontrar!
Jon Watte
151

Cuando desee ver archivos antiguos, realmente debe saber la diferencia entre:

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

y

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

La primera versión analiza la ruta que ahora está disponible como http: // server / svn / project / file y recupera ese archivo como estaba en la revisión 1234. (Por lo tanto, esta sintaxis no funciona después de eliminar un archivo).

La segunda sintaxis obtiene el archivo que estaba disponible como http: // server / svn / project / file en la revisión 1234. Por lo tanto, esta sintaxis FUNCIONA en archivos eliminados.

Incluso puede combinar estos métodos para recuperar un archivo que estaba disponible en la revisión 2345 como http: // server / svn / project / file pero con el contenido que tenía en 1234 con:

svn cat http://server/svn/project/file@2345 -r 1234
Bert Huijben
fuente
77
Gah, gracias! La respuesta principal actual en este hilo no menciona esto, ¡esto es genial!
Keith Palmer Jr.
Esto todavía falló para mí a menos que usara rutas absolutas, ya que mi cliente svn local estaba dando un error cuando no podía resolver ./local/filecuando el ./localdirectorio no existía. Esto podría no ser un problema para las versiones más nuevas de SVN.
Derrick Rice
2
@DerrickRice: en ese caso, la ^notación es útil: se refiere a la raíz del repositorio, por lo que puede decir svn cat ^/local/file@REV(dependiendo de la distancia entre la raíz del repositorio y la URL).
musiphil
Esto funciona muy bien en principio. Para las carpetas recibo lo siguiente:svn: E200009: Could not cat all targets because some targets are directories
Barney
Esta es la mejor respuesta. También tiene los votos más altos.
Felipe Alvarez
94

Primero, encuentre el número de revisión donde se eliminó el archivo:

svn log -v > log.txt

Luego busque en log.txt (no es un gurú SVN, así que no conozco una mejor manera) para obtener una línea con

D <deleted file>

y ver qué revisión fue esa. Luego, como en las otras respuestas, resucite el archivo utilizando la revisión anterior.

mjy
fuente
22
svn log -v | grep D "file.name"
abatishchev
18
+1 por ser la primera persona en responder correctamente la pregunta. No puede ver el contenido si no conoce la revisión antes de que se elimine.
Cerin
8
@abatishchev esto obtiene la lista de archivos eliminados, pero descarta la información de revisión, por lo que no es útil. También es lento si está trabajando con un repositorio grande / antiguo con mucho historial de cambios.
tchen
44
Bien, genial con la mejora de @ abatishchev. tchen: arreglado fácilmente usando un argumento de -B50 más o menos para grep, vea mi respuesta.
Jonas Byström
2
Otra buena forma de limitar la salida de svn log -v para repositorios muy grandes / antiguos es la opción -l. Entonces podría usar svn log -v -l 100 | grep D "file.name"
mindmatters
27

No es nada particularmente especial en git. Si conoce el nombre del archivo, puede encontrar el cambio que lo eliminó con log:

git log -n 1 -- filename

Luego puede usar esa confirmación para obtener el archivo tal como existía antes de la eliminación.

git checkout [last_revision]^ filename

Ejemplo:

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

Tenga en cuenta que esto en realidad no vuelve a colocar el archivo en el control de revisión. Simplemente deja caer el archivo tal como existía en su estado final en la ubicación actual. Luego puede agregarlo o simplemente inspeccionarlo o lo que sea desde ese punto.

Dustin
fuente
66
Maravillosa respuesta. El único problema es que la pregunta es sobre svn!
JohnK
16

Una solución que usa solo la GUI:

Si conoce el nombre del archivo, pero no sabe su último número de revisión o incluso su ruta:

  1. Desde el navegador Repo, haga un "Mostrar registro" en la raíz
  2. Presiona "Mostrar todo" (en la parte inferior del cuadro de diálogo de registro)
  3. Escriba el nombre del archivo en el cuadro de texto Filtro (en la parte superior del cuadro de diálogo de registro)

Esto mostrará solo aquellas revisiones donde el archivo fue agregado / modificado / eliminado. Este es tu historial del archivo.

Tenga en cuenta que si el archivo se eliminó eliminando una de sus carpetas principales, no tendrá una entrada 'eliminada' en el registro (y, por lo tanto, la solución de mjy no funcionará). En este caso, su entrada más reciente en el registro filtrado corresponderá a su contenido en la eliminación.

Mark Foreman
fuente
La fuerza bruta no siempre es la mierda. Especialmente no en grandes repositorios.
Jonas Byström
+1 para una única solución de IU. La línea de comando es excelente, y todo, pero no siempre es la mejor respuesta sin excepción. Especialmente cuando trabajas en un entorno que no controlas y no tienes fácil acceso de línea de comandos a SVN.
Mir
Tenga en cuenta que la respuesta anterior está destinada a la GUI TortoiseSVN.
Georg Muehlenberg el
13
svn log -v | grep -B50 YourDeletedFileName

Te conseguirá el camino y la revisión. En git (también busca cambios de nombre):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
Jonas Byström
fuente
¿Qué hace el -B50? Puedo obtener una lista de archivos usando svn log y grep con bastante facilidad usando los consejos aquí, pero parece que no puedo obtener los números de revisión que se muestran fácilmente, ya que se muestran en una línea diferente. Probé la cosa B50 y no pareció funcionar tan asombrosamente para mí.
cedd
Produce la línea con mates y las 50 líneas de arriba en caso de que alguien más esté leyendo esto.
cedd
8

Además de la respuesta de Dustin, si solo desea examinar el contenido y no verificarlo, en su ejemplo puede hacer:

$ git show 8d4a1f^:slosh.tac

the: separa una revisión y una ruta en esa revisión, solicitando efectivamente una ruta específica en una revisión específica.

Pieter
fuente
Ah, muy cierto. Solía ​​hacerlo de la manera muy, muy difícil. :)
Dustin
8

Usa este comando:

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

Esto enumerará todas las revisiones que alguna vez eliminaron cualquier archivo que coincida con el patrón. Es decir, si usted está en busca de fichero README, entonces todos /src/README, /src/README.firsty /some/deeply/hidden/directory/READMENOTserá encontrado y listado.

Si su nombre de archivo contiene barras diagonales (ruta), puntos u otros caracteres especiales de expresiones regulares, no olvide escapar de ellos para evitar desajustes o errores.

Alexander Amelkin
fuente
7

Si no conoce la ruta al archivo eliminado, resulta que puede buscarlo en el svn logcomando que de otro modo sería demasiado pesado :

svn log --search <deleted_file_or_pattern> -v

El comando probablemente está afectando al servidor tanto como lo haría sin la opción de búsqueda, pero al menos el resto de los recursos involucrados (incluidos sus globos oculares) se vería aliviado, ya que eso le indicará en qué revisión se eliminó ese archivo. Luego, puede seguir los otros consejos (principalmente utilizando el mismo svn logcomando, pero ya en una ruta definida).

JMB
fuente
svn log --search _test2.php -v... svn: opción no válida: --search ... :(
thinsoldier
5

El póster en realidad ha hecho 3 preguntas aquí:

  1. ¿Cómo miro el historial de un archivo eliminado en Subversion?
  2. ¿Cómo miro el contenido de un archivo eliminado en Subversion?
  3. ¿Cómo resucito un archivo eliminado en Subversion?

Todas las respuestas que veo aquí son para las preguntas 2 y 3.

La respuesta a la pregunta 1 es:

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

Todavía necesita obtener el número de revisión de cuándo existió el archivo por última vez, lo que otros responden claramente aquí.

dekeguard
fuente
4

Ah, como estoy aprendiendo a usar Bazaar, es algo que probé. Sin éxito, parece que no puede iniciar sesión y anotar archivos eliminados actualmente ... :-(

Intentó:

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

pero curiosamente (y afortunadamente) puedo hacer:

> bzr cat -r 3 Stuff/ErrorParser.hta

y:

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

y como se sugiere en el error anterior:

> bzr log -v | grep -B 1 ErrorParser

(ajuste el parámetro -B( --before-context) según sea necesario).

PhiLho
fuente
1

Tendría que especificar una revisión.

svn log -r <revision> <deleted file>
Jack M.
fuente
1
Esto da un error. Ejemplo: svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' ruta no encontrada
Jeremy
¿Estás seguro de que existió en esa revisión? Debe especificar una revisión donde realmente existía el archivo.
Jack M.
Vea la respuesta de Bert Huijben para conocer la extraña diferencia entre -r37428 y agregar @ 37428 a la URL SVN.
Dubek
1

Si desea ver el historial de un archivo antes de cambiarle el nombre, entonces, como se menciona en un comentario aquí , puede usar

git log --follow -- current_file_name
Andrew Grimm
fuente
1

Quería una respuesta, yo mismo. Pruebe lo siguiente para generar solo eliminaciones de 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 } }'

Esto filtra la salida del registro a través de awk . awk almacena en búfer cada línea de revisión que encuentra, emitiéndola solo cuando se encuentra un registro de eliminación. Cada revisión solo se genera una vez, por lo que se agrupan varias eliminaciones en una revisión (como en el estándarsvn log salida ).

Puede especificar a --limitpara reducir la cantidad de registros devueltos. También puede eliminar el --stop-on-copy, según sea necesario.

Sé que hay quejas sobre la eficiencia de analizar todo el registro. Creo que esta es una mejor solución que grep y su -Bopción de "lanzar una red amplia" . No sé si es más eficiente, pero no puedo pensar en una alternativa svn log. Es similar a la respuesta de @Alexander Amelkin, pero no necesita un nombre específico. También es mi primer guión awk , por lo que puede ser poco convencional.

nshew
fuente
1

Suponga que su archivo fue nombrado como ~ / 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

salida de muestra, la encontré en 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

cópielo de nuevo a la versión anterior (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .
Daniel YC Lin
fuente
0

Puede encontrar la última revisión que proporciona el archivo mediante la búsqueda binaria. He creado un /bin/bashscript simple para esto:

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
fuente
-1

Escribí un script php que copia el registro svn de todos mis repositorios en una base de datos mysql. Ahora puedo hacer búsquedas de texto completo en mis comentarios o nombres de archivos.

Thinsoldier
fuente