Jesper Ronn-Jensen
En un repositorio de código Git, quiero enumerar todas las confirmaciones que contienen una determinada palabra. probé esto
git log -p | grep --context=4 "word"
pero no necesariamente me devuelve el nombre del archivo (a menos que esté a menos de cinco líneas de la palabra que busqué. También intenté
git grep "word"
pero solo me da archivos actuales y no la historia.
¿Cómo busco en todo el historial para poder seguir los cambios en una palabra en particular? Tengo la intención de buscar en mi base de código apariciones de palabras para rastrear cambios (buscar en el historial de archivos).
Jakub Narębski
Si desea encontrar todas las confirmaciones en las que mensaje de compromiso contiene una palabra dada, use
$ git log --grep=word
Si desea encontrar todas las confirmaciones donde se agregó o eliminó “palabra” en el contenido del archivo (para ser más exactos: donde cambió el número de ocurrencias de “palabra”), es decir, buscar el confirmar contenidouse la llamada búsqueda ‘pickaxe’ con
$ git log -Sword
En Git moderno también hay
$ git log -Gword
buscar diferencias cuya línea agregada o eliminada coincide con “palabra” (también confirmar contenidos).
Algunas cosas a tener en cuenta:
-G
por defecto acepta una expresión regular, mientras que-S
acepta una cadena, pero se puede modificar para aceptar expresiones regulares usando el--pickaxe-regex
.-S
encuentra confirmaciones donde cambió el número de ocurrencias de “palabra”, mientras que-G
encuentra confirmaciones donde aparece “palabra” en la diferencia.- Esto significa que
-S<regex> --pickaxe-regex
y-G<regex>
no hagas exactamente lo mismo.
El git diff
documentación tiene una buena explicación de la diferencia:
Para ilustrar la diferencia entre
-S<regex> --pickaxe-regex
y-G<regex>
considere una confirmación con la siguiente diferencia en el mismo archivo:+ return frotz(nitfol, two->ptr, 1, 0); ... - hit = frotz(nitfol, mf2.ptr, 1, 0);
Mientras
git log -G"frotz\(nitfol"
mostrará este compromiso,git log -S"frotz\(nitfol" --pickaxe-regex
no lo hará (porque el número de ocurrencias de esa cadena no cambió).
Esto mostrará las confirmaciones que contienen los términos de búsqueda, pero si desea ver los cambios reales en esas confirmaciones, puede usar --patch
:
$ git log -G"searchTerm" --patch
Esto puede entonces ser canalizado a grep
para aislar la salida solo para mostrar líneas de confirmación de diferencia con ese término de búsqueda. Un caso de uso común es mostrar líneas de diferencias con ese término de búsqueda en confirmaciones desde e incluyendo una confirmación determinada: 3b5ab0f2a1
en este ejemplo – así:
$ git log 3b5ab0f2a1^.. -G"searchTerm" --patch | grep searchTerm
-
@TankorSmash
-S<string>
Busque diferencias que introduzcan o eliminen una instancia de. -G<string>
Busque diferencias cuya línea agregada o eliminada coincida con ladada. – m-ric
4 de noviembre de 2013 a las 20:19
-
@m-ric Oh, ya veo, ¡una instancia de una sola cadena, frente a una línea completa! Gracias
– TankorSmash
4 de noviembre de 2013 a las 20:35
-
@m-ric, @TankorSmash: La diferencia es que
-S<string>
es más rápido porque solo verifica si el número de ocurrencias de<string>
cambiado, mientras-G<string>
busca líneas añadidas y eliminadas en cada diferencia de confirmación.– Jakub Narębski
5 de noviembre de 2013 a las 17:18
-
Si necesita buscar palabras con espacios en medio,
git log --grep="my words"
.– MEM
21 de mayo de 2014 a las 12:45
-
@MEM,
--grep
es diferente de-S
y-G
. Puede citar la cadena para cada uno de estos argumentos.– Asclepio
12/08/2014 a las 20:33
u0b34a0f6ae
git log
El pico de encontrará confirmaciones con cambios que incluyen “palabra” con git log -Sword
-
Esto no es del todo preciso. -S
Busque diferencias que introduzcan o eliminen una instancia de . Tenga en cuenta que esto es diferente a la cadena que simplemente aparece en la salida diff; – tymtam
11 de agosto de 2011 a las 2:34
-
Si bien esta es generalmente la respuesta correcta, voté a la baja solo para alentar a otros a leer esta respuesta (stackoverflow.com/a/1340245/586983) que tiene 3 formas diferentes y explica sus sutilezas.
– jakeonrails
7 de enero de 2016 a las 19:18
-
¡Dios mio! No creo que sea una buena razón para rechazar una respuesta correcta… ¿no estabas seguro de que incluir el enlace en un comentario sería suficiente estímulo?
– Débora
24 de junio de 2016 a las 4:53
-
@jakeonrails, esa respuesta debería haber sido una edición de esta (más antigua), para que no tengamos estos molestos duplicados. Pero la gente solo quiere la reputación, en lugar de una página de respuestas limpia.
– Iulian Onofrei
6 de febrero de 2018 a las 14:56
-
Ejemplos de culpar a las personas en lugar del sistema. Stack Overflow debería tener formas más variadas y matizadas de: desviar la atención, recompensar la mejora, calificar y cuantificar, exaltar la esencia, aclarar y profundizar. Y para divagar sin desmerecer, guiño guiño guiño.
–Bob Stein
22 de enero de 2022 a las 17:56
Después de mucha experimentación, puedo recomendar lo siguiente, que muestra confirmaciones que introducen o eliminan líneas que contienen una expresión regular dada, y muestra los cambios de texto en cada una, con colores que muestran las palabras agregadas y eliminadas.
git log --pickaxe-regex -p --color-words -S "<regexp to search for>"
Sin embargo, tarda un poco en ejecutarse… 😉
-
Este es uno de los mejores hasta ahora gracias. Sugerencia: para enumerar todos los resultados sin paginación, anteponga el comando con
GIT_PAGER=cat
o añádelo con| cat
– Zack Morris
17/09/2018 a las 19:58
-
Especificar una ruta o un archivo sería mucho más rápido
git log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
– colmillo
26 de septiembre de 2019 a las 7:56
-
¿Se puede modificar esto para mostrar solo las líneas que coinciden con el patrón, en lugar de la diferencia completa? (Encontré la respuesta aquí: stackoverflow.com/a/51603771/1231241)
– Dannid
29 de enero de 2021 a las 17:03
-
Puede agregar un límite a la salida para evitar que se salga de control:
git log -n 1000 --pickaxe-regex -p --color-words -S "<regexp to search for>"
– Automático
30 de noviembre de 2021 a las 12:04
Una forma/sintaxis más para hacerlo es: git log -S "word"
Así puedes buscar por ejemplo git log -S "with whitespaces and stuff @/#ü !"
kenorb
Puedes probar el siguiente comando:
git log --patch --color=always | less +/searching_string
o usando grep
de la siguiente manera:
git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'
Ejecute este comando en el directorio principal donde le gustaría buscar.
-
Me gusta este método porque las confirmaciones que estoy viendo tienen cientos de líneas de cambios no relacionados, y solo estoy interesado en los parches reales que involucran la palabra que estoy buscando. Para obtener uso de color
git log --patch --color=always | less +/searching_string
.– Radón Rosborough
16/10/2016 a las 19:17
-
Para encontrar algo en las confirmaciones de basura, use:
git fsck | grep -Po '(?<=commit ).*' | GIT_PAGER xargs git grep 'search_string'
– galvá
12 de noviembre de 2020 a las 10:15
Pedro Mortensen
Para usar un conector booleano en una expresión regular:
git log --grep '[0-9]*\|[a-z]*'
Esta expresión regular busca la expresión regular [0-9]* o [a-z]* en mensajes de confirmación.
-
Me gusta este método porque las confirmaciones que estoy viendo tienen cientos de líneas de cambios no relacionados, y solo estoy interesado en los parches reales que involucran la palabra que estoy buscando. Para obtener uso de color
git log --patch --color=always | less +/searching_string
.– Radón Rosborough
16/10/2016 a las 19:17
-
Para encontrar algo en las confirmaciones de basura, use:
git fsck | grep -Po '(?<=commit ).*' | GIT_PAGER xargs git grep 'search_string'
– galvá
12 de noviembre de 2020 a las 10:15
Pedro Mortensen
Esto es útil en combinación con BFG (Rama de filtro de Git: no debe confundirse con git-filter-branch) y git-filter-repo. Simplemente obtiene las rutas de los archivos para que pueda ingresarlos en una de las dos herramientas que acabo de mencionar.
A. Rutas relativas, únicas, ordenadas:
# Get all unique filepaths of files matching 'password'
# Source: https://stackoverflow.com/a/69714869/10830091
git rev-list --all | (
while read revision; do
git grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"
done
) | sort | uniq
B. Nombres de archivo únicos, ordenados (no rutas):
# Get all unique filenames matching 'password'
# Source: https://stackoverflow.com/a/69714869/10830091
git rev-list --all | (
while read revision; do
git grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"
done
) | xargs basename | sort | uniq
Este segundo comando es útil para BFG, porque solo acepta nombres de archivo y no rutas relativas al repositorio/absolutas del sistema.
Ahí tienes Disfrute usando estos fragmentos de Bash por tanta agonía como me causaron a mí. Odio a Bash, entonces, ¿por qué sigo usándolo?
Disección
Obtener solo nombres de archivo/rutas
Cualquiera de las siguientes opciones significa lo mismo (documentación de git-rep):
-l
--files-with-matches
--name-only
En lugar de mostrar todas las líneas coincidentes, muestre solo los nombres de los archivos que contienen Blockquote
¿Es su patrón: A. Regex vs B. Fixed String?
Como para -F
bueno, solo significa usar una cadena fija en lugar de una expresión regular para la interpretación de patrones. Una fuente.
Otra nota útil que pertenece aquí: puede agregar -i
o --ignore-case
ser mayúsculas y minúsculas.
Deshazte de ese estúpido hash de confirmación principal
sed "s/[^:]*://"
Fuente.
¡Consígueles caminos únicos!
| sort | uniq
¿Quién quiere caminos duplicados? ¡Tú no, yo no! ¡Oh, mira, también están ordenados! Disfrutar.
Fuente: yo. He usado esto desde que tengo memoria. (man sort
y man uniq
)
¿Qué pasa con los nombres de archivo sin rutas?
xargs basename
Tu pensarias | basename
funcionaría, pero no. No acepta entrada entrada estándar, pero como argumentos de línea de comando. Aquí está una explicación para eso. ¡Imagínate! basename
básicamente devuelve el nombre de archivo principal sin su ruta principal. man basename
.
Para el método A., quiero rutas absolutas, no relativas.
Claro, solo dale una palmada realpath
al final. Al igual que:
) | sort | uniq | xargs realpath
Por supuesto que tienes que usar xargs
porque realpath
no utiliza la entrada estándar para la entrada. Utiliza argumentos de línea de comandos. Al igual que dirname
.
inspiraciones
- Echa un vistazo a esta increíble respuesta alternativa.
- Buscar en todo el historial de Git una cadena
- Nombres de archivo solo usando Git grep
-
¡Gracias por las ediciones @Peter Mortensen! Mi respuesta se ve aún más nítida ahora, con estos errores tipográficos y las URL desnudas corregidas. Sus descripciones de edición también son acertadas, ya que me ayudan a evitar repetir esos problemas corregidos.
– om-ja
29 de noviembre de 2021 a las 10:36
¿Posible duplicado de How to grep (buscar) código comprometido en el historial de git?
–Ortwin Gentz
5 de junio de 2018 a las 16:02