Então, encontrei a dúvida sobre como visualizar o histórico de alterações de um arquivo, mas o histórico de alterações desse arquivo em particular é enorme e estou realmente interessado apenas nas alterações de um método específico. Então, seria possível ver o histórico de alterações apenas para esse método específico?
Eu sei que isso exigiria git para analisar o código e que a análise seria diferente para diferentes linguagens, mas as declarações de método / função parecem muito semelhantes na maioria das linguagens, então pensei que talvez alguém tenha implementado esse recurso.
A linguagem que estou trabalhando atualmente é Objective-C e o SCM que estou usando é git, mas eu estaria interessado em saber se este recurso existe para qualquer SCM / linguagem.
Respostas:
Versões recentes de
git log
aprenderam uma forma especial do-L
parâmetro:Em outras palavras: se você pedir ao Git
git log -L :myfunction:path/to/myfile.c
, ele agora imprimirá o histórico de alterações daquela função.fonte
Usar
git gui blame
é difícil de usar em scripts e, emboragit log -G
egit log --pickaxe
possa mostrar a você quando a definição do método apareceu ou desapareceu, não encontrei nenhuma maneira de fazê-los listar todas as alterações feitas no corpo do seu método.No entanto, você pode usar
gitattributes
e atextconv
propriedade para reunir uma solução que faça exatamente isso. Embora esses recursos tenham sido originalmente planejados para ajudá-lo a trabalhar com arquivos binários, eles funcionam tão bem aqui.A chave é fazer com que o Git remova do arquivo todas as linhas, exceto aquelas em que você está interessado, antes de fazer qualquer operação diff. Em seguida
git log
,git diff
etc. verá apenas a área na qual você está interessado.Aqui está o esboço do que faço em outro idioma; você pode ajustá-lo para suas próprias necessidades.
Escreva um script de shell curto (ou outro programa) que receba um argumento - o nome de um arquivo de origem - e produza apenas a parte interessante desse arquivo (ou nada se nada disso for interessante). Por exemplo, você pode usar
sed
o seguinte:Defina um
textconv
filtro Git para seu novo script. (Consulte agitattributes
página do manual para obter mais detalhes.) O nome do filtro e a localização do comando podem ser o que você quiser.Diga ao Git para usar esse filtro antes de calcular as diferenças para o arquivo em questão.
Agora, se você usar
-G.
(observe o.
) para listar todos os commits que produzem mudanças visíveis quando seu filtro é aplicado, você terá exatamente aqueles commits nos quais está interessado. Quaisquer outras opções que usam as rotinas diff do Git, como--patch
, também obter essa visão restrita.Voilà!
Uma melhoria útil que você pode querer fazer é fazer com que o script do filtro tome um nome de método como seu primeiro argumento (e o arquivo como seu segundo). Isso permite que você especifique um novo método de interesse apenas chamando
git config
, em vez de ter que editar seu script. Por exemplo, você pode dizer:Claro, o script de filtro pode fazer o que você quiser, aceitar mais argumentos ou o que quer que seja: há muita flexibilidade além do que mostrei aqui.
fonte
O git log tem uma opção '-G' que pode ser usada para encontrar todas as diferenças.
Basta dar a ele um regex adequado do nome da função de seu interesse. Por exemplo,
fonte
--oneline
por-p
A coisa mais próxima que você pode fazer é determinar a posição de sua função no arquivo (por exemplo, digamos que sua função
i_am_buggy
esteja nas linhas 241-263 defoo/bar.c
) e, em seguida, execute algo no sentido de:Isso abrirá menos (ou um pager equivalente). Agora você pode digitar
/i_am_buggy
(ou o equivalente no seu pager) e começar a percorrer as alterações.Isso pode até funcionar, dependendo do estilo do seu código:
Isso limita a pesquisa desde o primeiro acerto dessa regex (de preferência, sua declaração de função) a trinta linhas depois disso. O argumento final também pode ser uma regexp, embora detectar isso com regexp's seja uma proposição mais duvidosa.
fonte
-L ":int myfunc:foo/bar.c"
e limitar à função com esse nome. Isso é fantástico - obrigado pelo ponteiro! Agora, se apenas a detecção da função fosse um pouco mais confiável ...A maneira correta é usar
git log -L :function:path/to/file
conforme explicado na resposta eckes .Mas, além disso, se sua função for muito longa, você pode querer ver apenas as mudanças que vários commits introduziram, não todas as linhas de função, incluídas não modificadas, para cada commit que talvez toque apenas uma dessas linhas. Como um normal
diff
faz.Normalmente
git log
pode ver as diferenças com-p
, mas não funciona com-L
. Então você tem quegrep
git log -L
mostrar apenas linhas envolvidas e cabeçalhos de commits / arquivos para contextualizá-los. O truque aqui é combinar apenas as linhas coloridas do terminal, adicionando--color
switch, com uma regex. Finalmente:Observe que
^[
deve ser real, literal^[
. Pode introduzi-los pressionando ^ V ^ [em bash, que é Ctrl+ V, Ctrl+ [. Referência aqui .Também a última
-3
opção, permite imprimir 3 linhas do contexto de saída, antes e depois de cada linha correspondida. Você pode querer ajustá-lo às suas necessidades.fonte
git blame mostra quem alterou pela última vez cada linha do arquivo; você pode especificar as linhas a serem examinadas de modo a evitar que o histórico de linhas fora de sua função.
fonte
git gui blame
você pode navegar pelas revisões mais antigas.Mostrar histórico de função
git log -L :<funcname>:<file>
como mostrado na resposta do eckes e no documento gitSe não mostrar nada, consulte Definindo um cabeçalho de hunk personalizado para adicionar algo semelhante
*.java diff=java
ao.gitattributes
arquivo para oferecer suporte ao seu idioma.Mostrar histórico de funções entre commits com
git log commit1..commit2 -L :functionName:filePath
Mostrar histórico de função sobrecarregada (pode haver muitas funções com o mesmo nome, mas com parâmetros diferentes) com
git log -L :sum\(double:filepath
fonte