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


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

Una solución muy pobre es grep el registro:

git log -p | grep <pattern>

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


1112
2018-05-28 11:36


origen


Respuestas:


Para buscar commit contenido (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 funcionará si se encuentra con un error de "lista de argumentos demasiado larga"

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

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

Esto grep a través de todo el texto de compromiso para regexp.

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

Solo imagine el siguiente escenario: grep podría encontrar lo mismo <regexp> en otros archivos que están contenidos en la misma revisión devuelta por rev-list (incluso si no hubo ningún cambio en ese archivo en esa revisión).

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

Árbol de búsqueda de trabajo para texto que coincide con expresiones regulares expresión regular:

git grep <regexp>

Buscar árbol de trabajo para líneas de texto que coincidan con la expresión regular regexp1 o regexp2:

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

Árbol de búsqueda de búsqueda para las líneas de texto que coinciden con la expresión regular regexp1 y regexp2, informando solo las rutas de archivos:

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

Buscar en el árbol de trabajo los archivos que tienen líneas de texto que coinciden con la expresión regular regexp1 y las líneas de texto que coinciden con la expresión regular regexp2:

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

Árbol de búsqueda de trabajo para líneas cambiadas de patrón de coincidencia de texto:

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

Buscar todas las revisiones de texto que coincidan con expresiones regulares expresiones regulares:

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

Buscar todas las revisiones entre rev1 y rev2 para el texto que coincida con la expresión regular de expresiones regulares:

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

1483
2018-05-28 13:47



Deberías usar el pico (-S) opción de git log

Buscar Foo:

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

Ver Historial de Git: encuentra la línea perdida por palabra clave para más.


Como Jakub Narębski comentado:

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

  • el --pickaxe-regex la opción le permite usar expresiones rex de POSIX extendidas en lugar de buscar una cadena.


Como Robar comentó, esta búsqueda es sensible a mayúsculas y minúsculas, abrió una siguiente pregunta sobre cómo buscar las mayúsculas y minúsculas.


439
2018-05-28 11:57



Mi forma favorita de hacerlo es con git loges -G opción (agregada en la versión 1.7.4).

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

Hay una sutil diferencia entre la forma en que -G y -S las opciones determinan si una confirmación coincide:

  • los -S la opción básicamente cuenta el número de veces que su búsqueda coincide en un archivo antes y después de una confirmación. La confirmación se muestra en el registro si los recuentos antes y después son diferentes. Esto no mostrará, por ejemplo, commits donde se movió una línea que coincide con su búsqueda.
  • Con el -G opción, la confirmación se muestra en el registro si su búsqueda coincide con cualquier línea que se agregó, eliminó o modificó.

Tome este compromiso como un ejemplo:

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

Como la cantidad de veces que "hello" aparece en el archivo es la misma antes y después de esta confirmación, no coincidirá con -Shello. Sin embargo, dado que hubo un cambio en una línea coincidente hello, el compromiso se mostrará usando -Ghello.


204
2017-09-14 18:34



Si desea navegar por los cambios de código (vea lo que en realidad se ha cambiado con la palabra dada en todo el historial) vaya a patch modo - 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 ;) )

33
2018-04-17 08:17



Yo tomé @ La respuesta de Jeet y lo 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 alguna razón, la confirmación real que eliminó esta expresión regular no apareció en el resultado del comando, sino más bien una confirmación anterior.


22
2017-11-17 09:35



Busca en cualquier revisión, cualquier archivo:

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

Busque solo en algunos archivos determinados, 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ó ...

A continuación, puede obtener más información como autor, fecha, diferencia utilizando git show:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af

10
2018-04-02 15:03



git log puede ser una forma más efectiva de buscar texto en todas las ramas, especialmente si hay muchas coincidencias, y desea ver primero cambios más recientes (relevantes).

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

Estos comandos de registro enumeran los commits que agregan o eliminan la cadena de búsqueda dada / regex, (generalmente) la más reciente primero. los -p La opción hace que se muestre la diferencia relevante donde se agregó o quitó el patrón, para que pueda verlo en contexto.

Después de haber encontrado un compromiso relevante que agrega el texto que estabas buscando (por ejemplo, 8beeff00d), busca las ramas que contienen la confirmación:

git branch -a --contains 8beeff00d

8
2018-06-23 00:38



Para cualquier otra persona que intente hacer esto en SourceTree, no hay un comando directo en la interfaz de usuario para ello (a partir de la versión 1.6.21.0). Sin embargo, puede usar los comandos especificados en la respuesta aceptada al abrir Terminal ventana (botón disponible en la barra de herramientas principal) y copiar / pegar en el mismo.

Nota: SourceTree's Buscar view puede hacer una búsqueda de texto en parte. prensa Ctrl + 3 para ir a la vista de Búsqueda (o haga clic en la pestaña Buscar disponible en la parte inferior). Desde la extrema derecha, establezca el tipo de búsqueda en Cambios de archivos 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 el confirma 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.

5
2017-10-01 05:51