Cómo buscar (buscar) código comprometido en el historial de Git
Eliminé un archivo o algún código en un archivo en algún momento del pasado. ¿Puedo buscar en el contenido (no solo en los mensajes de confirmación)?
Una solución muy pobre es recuperar el registro:
git log -p | grep <pattern>
Sin embargo, esto no devuelve el hash de confirmación de inmediato. Jugué git grep
sin éxito.
Para buscar contenido de confirmación (es decir, líneas de fuente reales, a diferencia de mensajes de confirmación y similares), debe hacer:
git grep <regexp> $(git rev-list --all)
git rev-list --all | xargs git grep <expression>
funcionará si se encuentra con el error "Lista de argumentos demasiado larga".
Si desea limitar la búsqueda a algún subárbol (por ejemplo, "lib/util"), deberá pasarlo al rev-list
subcomando y grep
también:
git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util
Esto revisará todo el texto de confirmación de regexp
.
La razón para pasar la ruta en ambos comandos es porque rev-list
devolverá la lista de revisiones donde lib/util
ocurrieron todos los cambios, pero también debe pasar grep
para que solo busque en lib/util
.
Imagínese el siguiente escenario: grep
podría encontrar lo mismo <regexp>
en otros archivos contenidos en la misma revisión devuelta rev-list
(incluso si no hubo ningún cambio en ese archivo en esa revisión).
A continuación se muestran otras formas útiles de buscar su fuente:
Busque en el árbol de trabajo texto que coincida con expresiones regulares regexp:
git grep <regexp>
Busque en el árbol de trabajo 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 líneas de texto que coincidan con las expresiones regulares regexp1 y regexp2, informando únicamente las rutas de los archivos:
git grep -l -e <regexp1> --and -e <regexp2>
Busque en el árbol de trabajo 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 líneas modificadas de patrón de coincidencia de texto:
git diff --unified=0 | grep <pattern>
Busque en todas las revisiones texto que coincida con expresiones regulares regexp:
git grep <regexp> $(git rev-list --all)
Busque en todas las revisiones entre rev1 y rev2 texto que coincida con expresión regular regexp:
git grep <regexp> $(git rev-list <rev1>..<rev2>)
Debes utilizar la opción pico ( -S
) 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
Consulte el historial de Git: busque líneas perdidas por palabra clave para obtener más información.
-S
(llamado pickaxe
) proviene originalmente de una git diff
opción (Git v0.99, mayo de 2005). Luego -S
( pickaxe
) fue portadogit log
en mayo de 2006 con Git 1.4.0-rc1.
Como comentó Jakub Narębski :
esto busca diferencias que introducen o eliminan una instancia de
<string>
. Por lo general, significa "revisiones en las que agregó o eliminó una línea con 'Foo'".la
--pickaxe-regex
opción le permite utilizar expresiones regulares POSIX extendidas en lugar de buscar una cadena. Ejemplo (degit log
):git log -S"frotz\(nitfol" --pickaxe-regex
Como comentó Rob , esta búsqueda distingue entre mayúsculas y minúsculas; abrió una pregunta de seguimiento sobre cómo realizar búsquedas que no distinguen entre mayúsculas y minúsculas.
Hola Angel señala en los comentarios :
Ejecutar a
git log -G<regexp> --branches --all
(-G
es lo mismo-S
pero para expresiones regulares) hace lo mismo que el aceptado (git grep <regexp> $(git rev-list --all)
), ¡pero es muchísimo más rápido!La respuesta aceptada seguía buscando texto después de ≈10 minutos de ejecutarlo, mientras que esta da resultados después de ≈4 segundos 🤷♂️. El resultado aquí también es más útil.