Entonces encontré la pregunta sobre cómo ver el historial de cambios de un archivo, pero el historial de cambios de este archivo en particular es enorme y realmente solo estoy interesado en los cambios de un método en particular. Entonces, ¿sería posible ver el historial de cambios solo para ese método en particular?
Sé que esto requeriría que git analizara el código y que el análisis sería diferente para diferentes lenguajes, pero las declaraciones de método / función se ven muy similares en la mayoría de los lenguajes, así que pensé que tal vez alguien haya implementado esta característica.
El idioma con el que estoy trabajando actualmente es Objective-C y el SCM que estoy usando actualmente es git, pero me interesaría saber si esta función existe para cualquier SCM / idioma.
Respuestas:
Las versiones recientes de
git log
aprendieron una forma especial del-L
parámetro:En otras palabras: si le pides a Git que
git log -L :myfunction:path/to/myfile.c
lo haga, ahora imprimirá felizmente el historial de cambios de esa función.fuente
El uso
git gui blame
es difícil de hacer uso de secuencias de comandos, y al mismo tiempogit log -G
, ygit log --pickaxe
cada uno puede mostrar que cuando la definición del método apareció o desapareció, no he encontrado ninguna manera de hacer que hagan una lista de todos los cambios realizados en el cuerpo de su método.Sin embargo, puede usar
gitattributes
y latextconv
propiedad para armar una solución que haga precisamente eso. Aunque estas características originalmente estaban destinadas a ayudarle a trabajar con archivos binarios, funcionan igual de bien aquí.La clave es hacer que Git elimine del archivo todas las líneas excepto las que le interesan antes de realizar cualquier operación de diferenciación. Entonces
git log
,git diff
etc. verá sólo el área que le interesa.Aquí está el esquema de lo que hago en otro idioma; puede modificarlo según sus propias necesidades.
Escriba un breve script de shell (u otro programa) que tome un argumento, el nombre de un archivo fuente, y muestre solo la parte interesante de ese archivo (o nada si ninguno es interesante). Por ejemplo, puede utilizar
sed
lo siguiente:#!/bin/sh sed -n -e '/^int my_func(/,/^}/ p' "$1"
Defina un
textconv
filtro Git para su nuevo script. (Consulte lagitattributes
página de manual para obtener más detalles). El nombre del filtro y la ubicación del comando pueden ser los que desee.Dile a Git que use ese filtro antes de calcular las diferencias para el archivo en cuestión.
$ echo "my_file diff=my_filter" >> .gitattributes
Ahora, si usa
-G.
(tenga en cuenta.
) para enumerar todas las confirmaciones que producen cambios visibles cuando se aplica su filtro, tendrá exactamente las confirmaciones que le interesan. Cualquier otra opción que use las rutinas diff de Git, como--patch
, también obtenga esta vista restringida.¡Voilà!
Una mejora útil que podría querer hacer es que su script de filtro tome un nombre de método como primer argumento (y el archivo como segundo). Esto le permite especificar un nuevo método de interés simplemente llamando
git config
, en lugar de tener que editar su secuencia de comandos. Por ejemplo, podrías decir:$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Por supuesto, el script de filtro puede hacer lo que quiera, aceptar más argumentos o lo que sea: hay mucha flexibilidad más allá de lo que he mostrado aquí.
fuente
git log tiene una opción '-G' que podría usarse para encontrar todas las diferencias.
Solo dale una expresión regular adecuada del nombre de la función que te interesa. Por ejemplo,
$ git log --oneline -G'^int commit_tree' 40d52ff make commit_tree a library function 81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory 7b9c0a6 git-commit-tree: make it usable from other builtins
fuente
--oneline
con-p
Lo más cercano que puede hacer es determinar la posición de su función en el archivo (por ejemplo, digamos que su función
i_am_buggy
está en las líneas 241-263 defoo/bar.c
), luego ejecute algo con el efecto de:git log -p -L 200,300:foo/bar.c
Esto abrirá menos (o un localizador equivalente). Ahora puede escribir
/i_am_buggy
(o su equivalente en buscapersonas) y comenzar a revisar los cambios.Esto incluso podría funcionar, dependiendo de su estilo de código:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
Esto limita la búsqueda desde el primer hit de esa expresión regular (idealmente su declaración de función) a treinta líneas después de eso. El argumento final también puede ser una expresión regular , aunque detectar eso con expresiones regulares es una proposición más dudosa.
fuente
-L ":int myfunc:foo/bar.c"
y limitar a la función con ese nombre. Esto es fantástico, ¡gracias por el puntero! Ahora, si solo la detección de funciones fuera un poco más confiable ...La forma correcta es usarlo
git log -L :function:path/to/file
como se explica en la respuesta de eckes .Pero además, si su función es muy larga, es posible que desee ver solo los cambios que han introducido varias confirmaciones, no todas las líneas de función, incluidas sin modificar, para cada confirmación que tal vez toque solo una de estas líneas. Como lo hace una persona normal
diff
.Normalmente
git log
puede ver diferencias con-p
, pero esto no funciona con-L
. Por lo tanto,grep
git log -L
debe mostrar solo las líneas involucradas y el encabezado de confirmaciones / archivos para contextualizarlos. El truco aquí es hacer coincidir solo las líneas de color de la terminal, agregando un--color
interruptor, con una expresión regular. Finalmente:git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Tenga en cuenta que
^[
debe ser real, literal^[
. Puede escribirlos presionando ^ V ^ [en bash, es decir Ctrl+ V, Ctrl+ [. Referencia aquí .También último
-3
interruptor, permite imprimir 3 líneas de contexto de salida, antes y después de cada línea emparejada. Es posible que desee ajustarlo a sus necesidades.fuente
git blame te muestra quién cambió por última vez cada línea del archivo; puede especificar las líneas a examinar para evitar que el historial de líneas esté fuera de su función.
fuente
git gui blame
puede navegar por revisiones anteriores.Muestra el historial de funciones con
git log -L :<funcname>:<file>
como se muestra en la respuesta de eckes y git docSi no muestra nada, consulte Definición de un encabezado de trozo personalizado para agregar algo similar
*.java diff=java
al.gitattributes
archivo para admitir su idioma.Mostrar historial de funciones entre confirmaciones con
git log commit1..commit2 -L :functionName:filePath
Muestra el historial de funciones sobrecargado (puede haber muchas funciones con el mismo nombre, pero con diferentes parámetros) con
git log -L :sum\(double:filepath
fuente