¿Cómo grep el git diff?

81

¿Hay alguna forma de mostrar el git-diff filtrado por un patrón determinado?

Algo como

git grepdiff pattern

changed file
+++ some sentence with pattern
changed file 2
--- some other pattern

Desafortunadamente, la solución más simple no es lo suficientemente buena.

git diff | grep pattern 

+++ some sentence with pattern
--- some other pattern
# not an option as doesn't put the filename close to the match

Vine con una solución usando awk

git diff | awk "/\+\+\+/{f = \$2}; /PATTERN/ {print f \$0} "

Pero me encantaría saber que existe un comando para esto.

Kuba
fuente
3
Aparentemente, el proyecto github llamado git-diff-grep hace algo completamente diferente.
Kuba

Respuestas:

98

¿No está seguro, pero la git diff -G <regex>bandera no está bien?

-G <expresión regular>

Look for differences whose added or removed line matches the given <regex>.
CharlesB
fuente
15
eso no es exactamente lo que estoy buscando, ya que quiero ver solo las líneas, que coinciden con el patrón, no todo el diff de los archivos, que incluyen el cambio con el patrón
Kuba
entonces supongo que no hay una solución más simple que la tuya
CharlesB
Al menos git diff -G es un mejor primer paso que el git diff completo.
Kuba
1
Mi versión no tiene la bandera -G. ¿Fue eliminado?
RedX
3
También es útil para ver qué archivos se vieron afectados por la expresión regular:git diff -G <regex> --raw
Raman
11

¿Has probado git diff -S<string>o git diff -G".*string.*"? Tenga en cuenta que no son equivalentes, consulte la documentación sobre pico para saber qué hace -S.

Robinst
fuente
11

Otra posibilidad sería ver la diferencia completa y buscar la salida usando los lesscomandos normales (escriba /y luego el patrón).

Cuando haya lessconfigurado para mostrar algunas líneas antes del uso de la coincidencia --jump-target=N, esto es bastante útil. Pruébelo así:

PAGER="/usr/bin/less --jump-target=10" git diff

Esto significa que la coincidencia debe mostrarse en la línea 10 (muestra 9 líneas de contexto arriba), lo que puede ser suficiente para ver también el nombre del archivo.

También puede usar, por ejemplo, --jump-target=.5para hacer que coloque la cerilla en el medio de la pantalla.

Robinst
fuente
3

Yo uso git log -p, que abre menos (aunque configurable), que a su vez se puede buscar con /. También hay git log -S <searchword>.

chelmertz
fuente
Estoy familiarizado con ellos, no estoy mirando en la historia, sino en los cambios de trabajo actuales.
Kuba
Muy bien, entonces se podría usar el mismo método (como lo citó Robinst). Si desea la salida, probablemente podría usar cualquier biblioteca usando libgit2 o gitgui / gitk.
chelmertz
1

Esto funcionó para mí, espero que ayude a alguien:

git diff | grep  -P '^\+|^\-'
petiar
fuente
1

Creo que su enfoque de la diffsalida "grep" es la mejor solución.

Puede mejorar su script awk usando sed:

colored="(^[\[[0-9;]*[a-zA-Z])"
marker="^$colored+diff"
pattern="^$colored+.*(\+|\-).*PATTERN"
git diff --color | sed -rn -e "/$marker/! H; /$marker/ ba; $ ba; b; :a; x; /$pattern/ p"
  • colored: regex para que coincida con las líneas de color de la terminal
  • marker: marcador para coincidir con la división de diferentes difftrozos, líneas que comienzan con "diff" de color
  • pattern: patrón para buscar, líneas que comienzan con el color "+" o "-" y contienen "PATRÓN"

Esto imprimirá trozos de diferencias completas, con PATRÓN agregado o eliminado, manteniendo también una salida de color útil.

Tenga ^[en cuenta que coloreddebe ser real, literal ^[. Puede escribirlos en bash presionando Ctrl+ V, Ctrl+[

Hazzard17
fuente
¡¡excelente!! para cualquiera que intente escribir esto en otro lugar que no sea un shell bash (por ejemplo, editando el archivo .sh en IDE) debe reemplazar el me ^[gusta colored=$'(\e\[[0-9;]*[a-zA-Z])'y en macOS también debe hacerlo brew install gnu-sedy reemplazarlosed --> gsed
Anentropic
0

Aquí hay una herramienta de diferencias personalizada que permite grepping dentro de los cambios (pero no el contexto):

Uso

GIT_EXTERNAL_DIFF="mydiff --grep foo" git diff

Esto generará esas líneas en sus cambios que contienen foo(incluidas las líneas donde foodesaparecieron debido a sus cambios). Se puede usar cualquier patrón grep en lugar de foo.

Cada línea de salida comienza con el siguiente prefijo:

filename: oldlinenum: newlinenum|

El script también se puede usar sin la --grepopción, en cuyo caso simplemente formatea la diferencia completa (es decir, proporciona el contexto completo) como se describe anteriormente.

mydiff

#!/bin/bash

my_diff()
{
    diff --old-line-format="$1"':%6dn:      |-%L'     \
         --new-line-format="$1"':      :%6dn|+%L'     \
         --unchanged-line-format="$1"':%6dn:%6dn| %L' \
         $2 $3
}

if [[ $1 == '--grep' ]]
then
    pattern="$2"
    shift 2
    my_diff "$1" "$2" "$5"|grep --color=never '^[^|]\+|[-+].\+'"$pattern"'.*'
else
    my_diff "$1" "$2" "$5"
fi

exit 0
León
fuente
0

En Windows, una solución simple es:

git diff -U0 | findstr string

Si desea agrupar por nombre de archivo, use este

FOR /F "usebackq delims==" %i IN (`git diff --name-only`) do git diff -U0 %~fi | findstr string
Horacio
fuente
0

He estado usando esto con gran satisfacción :)

grep -ri <MY_PATTERN> $(git diff 790e26393d --name-only) 
Hrishikesh
fuente