Git: muestra todos los cambios en una sola línea en un archivo específico en todo el historial de git

112

He mirado a mi alrededor y no estoy seguro de si esto es posible, pero aquí va:

Tengo un archivo (javascript) (digamos /lib/client.js) en el que tengo un identificador único asignado a una variable, así: var identifier = "SOME_IDENTIFIER";

Puede pensar en el identificador como un número de versión: periódicamente, cambiaremos esta variable por un nuevo identificador.

Lo que me gustaría hacer es encontrar todos los identificadores únicos que hemos usado. ¿Cómo puedo hacer esto con git?

Imagino que podría haber una forma de buscar en el historial de git e imprimir la coincidencia de líneas "var identifier =". Podría eliminar esta lista manualmente.

De todos modos, agradecería cualquier información aquí. Gracias.

Findchris
fuente

Respuestas:

106

Desde git 1.8.4 , hay una forma más directa de responder a su pregunta.

Suponiendo que esa línea 110es la línea que dice var identifier = "SOME_IDENTIFIER";, haga esto:

git log -L110,110:/lib/client.js

Esto devolverá cada confirmación que tocó esa línea de código.

[ Documentación de Git (consulte el parámetro de línea de comandos "-L")]

Alexander Bird
fuente
49

Consulte la página de manual para git-logy gitdiffcore. Creo que este comando lo haría, pero puede que no sea del todo correcto:

git log -G "var identifier =" file.js

EDITAR: Aquí hay un comienzo aproximado para que un script bash muestre las líneas reales. Esto podría ser más lo que estás buscando.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Se utiliza git log -Gpara encontrar las confirmaciones interesantes, utilizando --format=%Hpara producir una lista de hashes de confirmación. Luego itera sobre cada confirmación interesante, pidiendo git grepmostrar las líneas de esa confirmación y el archivo que contiene la expresión regular, precedida por el hash de confirmación.


EDITAR: Cambiado para usar en -Glugar de -Scomo se sugiere en los comentarios.

robar
fuente
@Rob - gracias por esto - sin embargo, una pequeña edición en su script - poner solo el nombre del archivo solo muestra las confirmaciones que solo afectan ese archivo - si una confirmación hace referencia a otros archivos, no está en la lista
Adrian Cornish
@AdrianCornish - Me alegro de que haya sido útil. Creo que el OP solo quería ver un archivo, pero tiene bastante razón en que eliminar el nombre del archivo es probablemente un script más útil en general.
robar el
Tengo una situación más difícil. El archivo en cuestión se movió de paht_a / file a path_b / file. Ahora, cuando lo hago en path_b, solo muestra los cambios hasta cuando el archivo se mueve de path_a a path_b. Si lo hago en path_a me dice fatal: argumento ambiguo 'archivo': revisión desconocida o ruta que no está en el árbol de trabajo.
Andy Song
@AndySong: si la cadena que está buscando es lo suficientemente única, tal vez pueda omitir el nombre del archivo y aún así obtener lo que está buscando.
robo
Fue más conveniente para mí: coloque una línea en blanco después de cada confirmación, enumere las líneas:sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
John_West
14

También puedes hacer esto con gitk:

gitk file.js

En el menú desplegable "confirmar", elija "agregar / quitar cadena:" y en el cuadro de texto junto a él, ingrese "var identifier =", y se resaltará cualquier confirmación que agregue o elimine líneas que contengan esa cadena.

Ethan Brown
fuente
Esto ayudó a identificar la confirmación en la que se agregó la línea que contiene "var identifier =", pero no muestra las confirmaciones posteriores que modificaron esta línea.
findchris
2
¿Has probado git blame file.jso git gui blame file.js?
Ethan Brown
1
Sé lo que hace la culpa; Estoy buscando un historial completo de revisiones, ni una sola diferencia.
findchris
1
git gui blame file.jshará eso ... le mostrará todas las revisiones de un archivo y quién lo cambió; puede simplemente hacer clic hacia atrás a través del historial.
Ethan Brown
Terminé avanzando visualmente con gitk. Me imagino que hay una técnica git elegante para hacer esto, pero gitk fue lo suficientemente bueno. Gracias.
findchris
9

Si adapta la respuesta de @ rob solo un poco, git logbásicamente lo hará por usted, si todo lo que necesita es una comparación visual:

git log -U0 -S "var identifier =" path/to/file

-U0significa salida en modo parche ( -p), y muestra cero líneas de contexto alrededor del parche.

Incluso puede hacer esto en todas las ramas:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Puede haber una forma de suprimir el encabezado diff, pero no conozco ninguna.

Andrés
fuente
¡Trabajó para mi! Gracias.
Roberto Bonini
3

En magit , puedes hacer esto con

l, =L

Luego le pedirá el archivo y las líneas iniciales y finales.

barrios marginales
fuente