ver - github




¿Cómo grep(buscar) código comprometido en el historial de git? (9)

Buscar en cualquier revisión, cualquier archivo :

git rev-list --all | xargs git grep <regexp>

Buscar solo en algunos archivos dados, por ejemplo archivos xml:

git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"

Las líneas de resultados deberían verse así: 6988bec26b1503d45eb0b2e8a4364afb87dde7af: bla.xml: texto de la línea que encontró ...

Luego puede obtener más información como autor, fecha, diff usando git show:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af

He eliminado un archivo o un código en un archivo en el pasado. ¿Puedo grep en el contenido (no en los mensajes de confirmación)?

Una solución muy mala es grep el registro:

git log -p | grep <pattern>

Sin embargo, esto no devuelve el hash de confirmación de inmediato. git grep con git grep en vano.


Deberías usar la opción pickaxe ( -S ) del git log de git log

Para buscar Foo :

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

Consulte el historial de Git: encuentre la línea perdida por palabra clave para obtener más información.

Como comentó Jakub Narębski :

  • esto busca diferencias que introducen o eliminan una instancia de <string> .
    Por lo general, significa "revisiones donde agregó o quitó la línea con 'Foo'".

  • La opción --pickaxe-regex permite utilizar --pickaxe-regex POSIX extendidas en lugar de buscar una cadena.

Como comentó Rob , esta búsqueda distingue entre mayúsculas y minúsculas: abrió una pregunta de seguimiento sobre cómo realizar una búsqueda sin distinción de mayúsculas y minúsculas.


Entonces, ¿estás tratando de pasar grep a través de versiones anteriores del código para ver dónde existe algo último?

Si estuviera haciendo esto, probablemente usaría git bisect . Usando bisect, puede especificar una versión buena conocida, una versión mala conocida y un script simple que verifique si la versión es buena o mala (en este caso, un grep para ver si el código que busca está presente) ). Ejecutando esto encontrará cuando el código fue eliminado.


La respuesta de @Jeet funciona en PowerShell.

git grep -n <regex> $(git rev-list --all)

A continuación se muestran todos los archivos, en cualquier confirmación, que contienen una password .

# store intermediate result
$result = git grep -n "password" $(git rev-list --all)

# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }

Para buscar contenido de confirmación (es decir, líneas de origen reales, en lugar de mensajes de confirmación y similares), lo que debe hacer es:

git grep <regexp> $(git rev-list --all)

Actualizaciones : git rev-list --all | xargs git grep <expression> git rev-list --all | xargs git grep <expression> funcionará si te encuentras con un error "Lista de argumentos demasiado larga"

Si desea limitar la búsqueda a algún subárbol (por ejemplo, "lib / util"), también deberá pasarlo al subcomando rev-list y grep :

git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util

Esto hará grep a través de todo su texto de confirmación para la expresión regular.

La razón para pasar la ruta en ambos comandos es porque rev-list devolverá la lista de revisiones donde ocurrieron todos los cambios a lib/util , pero también debe pasar a grep para que solo busque en lib/util .

Imagínese el siguiente escenario: grep puede encontrar el mismo <regexp> en otros archivos que se encuentran en la misma revisión devuelta por rev-list (incluso si no hubo cambios en ese archivo en esa revisión).

Aquí hay algunas otras formas útiles de buscar su fuente:

Busque en el árbol de trabajo el texto que coincida con la expresión regular regexp:

git grep <regexp>

Busque en el árbol de trabajo las líneas de texto que coincidan con la expresión regular regexp1 o regexp2:

git grep -e <regexp1> [--or] -e <regexp2>

Busque en el árbol de trabajo las líneas de texto que coincidan con las expresiones regulares regexp1 y regexp2, que solo reporten rutas de archivos:

git grep -e <regexp1> --and -e <regexp2>

Busque en el árbol de trabajo los archivos que tengan líneas de texto que coincidan con la expresión regular regexp1 y líneas de texto que coincidan con la expresión regular regexp2:

git grep -l --all-match -e <regexp1> -e <regexp2>

Busque en el árbol de trabajo las líneas cambiadas de patrón de coincidencia de texto:

git diff --unified=0 | grep <pattern>

Busque en todas las revisiones el texto que coincida con expresiones regulares regexp:

git grep <regexp> $(git rev-list --all)

Busque en todas las revisiones entre rev1 y rev2 el texto que coincida con expresiones regulares regexp:

git grep <regexp> $(git rev-list <rev1>..<rev2>)

Para cualquier otra persona que intente hacer esto en SourceTree , no hay un comando directo en la IU para ello (a partir de la versión 1.6.21.0). Sin embargo, puede usar los comandos especificados en la respuesta aceptada abriendo la ventana de Terminal (botón disponible en la barra de herramientas principal) y copiándolos / pegándolos en la misma.

Nota: la vista de búsqueda de SourceTree puede realizar búsquedas de texto en parte. Presione Ctrl + 3 para ir a la vista Buscar (o haga clic en la pestaña Buscar disponible en la parte inferior). Desde el extremo derecho, establezca Tipo de búsqueda en Cambios de archivo y luego escriba la cadena que desea buscar. Este método tiene las siguientes limitaciones en comparación con el comando anterior:

  1. SourceTree solo muestra las confirmaciones que contienen la palabra de búsqueda en uno de los archivos modificados. Encontrar el archivo exacto que contiene el texto de búsqueda es nuevamente una tarea manual.
  2. RegEx no es compatible.

Si desea buscar cambios en el código (vea lo que realmente se ha cambiado con la palabra dada en todo el historial) opte por el modo de patch : encontré una combinación muy útil de hacer:

git log -p
# hit '/' for search mode
# type in the word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )

Tomé la respuesta de @ Jeet y la adapté a Windows (gracias a esta respuesta ):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

Tenga en cuenta que para mí, por algún motivo, el compromiso real que eliminó esta expresión regular no apareció en la salida del comando, sino más bien un compromiso anterior.


git rev-list --all | xargs -n 5 git grep EXPRESSION

es una modificación para la solución de @ Jeet, por lo que muestra resultados mientras se busca y no solo al final (lo que puede llevar mucho tiempo en un gran repositorio).





diff