Portanto, como o GitHub removeu a guia de insights para contas não premium, estou tentando listar localmente inserções e exclusões em meu repositório git por dia.
Eu descobri esta maneira de imprimir o que quero:
git log --pretty="@%ad" --date=short --shortstat | tr "\n" " " | tr "@" "\n"
Isso produz este tipo de saída:
2024-06-13 7 files changed, 400 insertions(+), 406 deletions(-)
2024-06-12 3 files changed, 145 insertions(+)
2024-06-12 5 files changed, 638 deletions(-)
2024-06-12 1 file changed, 1 insertion(+), 1 deletion(-)
Observe os plurais em arquivo(s), inserção(ões) e exclusão(ões). Outro problema é que um commit pode não ter inserções ou exclusões (ou ambas, mas vamos ignorar este caso).
Então estou quase lá, só preciso extrair a data, inserções e exclusões e agrupar por data. Isso produzirá algum tipo de gráfico de “trabalho realizado por dia”.
Fiz esse regex para capturar os campos que tratam de todos os opcionais:
/^([0-9]{4}-[0-9]{2}-[0-9]{2})\s{3}[0-9]+\sfile(s)?\schanged,\s(([0-9]+)\sinsertion(s)?\(\+\))?(,\s)?(([0-9]+)\sdeletion(s)?\(\-\))?\s$/gm
Agora preciso obter o 1º, 4º e 8º grupos, por exemplo com sed
:
echo "2024-06-13 7 files changed, 400 insertions(+), 406 deletions(-) " |
sed -r 's/^([0-9]{4}-[0-9]{2}-[0-9]{2})\s{3}[0-9]+\sfile(s)?\schanged,\s(([0-9]+)\sinsertion(s)?\(\+\))?(,\s)?(([0-9]+)\sdeletion(s)?\(\-\))?\s$/\1 \4 \8/gm'
Isso produz a saída correta:
2024-06-13 400 406
Mas se a string de entrada não tiver inserções ou exclusões, sed simplesmente não imprimirá nada para esse grupo capturado. Ex.:
2024-06-13 400
E não tenho como saber se o número único são inserções ou exclusões.
Existe alguma maneira de extrair os grupos de cada linha, mas imprimir um "0" como espaço reservado se o grupo não existir? (não necessariamente apenas com sed e não necessariamente em um único comando).
Sempre há muitas soluções possíveis. Aqui está um. Gosto de um único regexp que faça tudo, mas às vezes é melhor mantê-lo simples e passo a passo:
Isso corresponde à data e adiciona ao final da linha a string de espaço reservado "
XXX C0 I0 D0
". Os próximos 3 comandos substituem o apropriado0
pelo número real de itens alterados, inseridos ou excluídos. Toda a linha desde o final da data até o espaço reservado é removida e as letras C, D e I são removidas, deixando apenas os números atualizados anexados a elas.Se o espaço reservado intermediário estiver vazio, você terá um espaço duplo, que poderá preencher com um zero. Da mesma forma, se você não tiver o último item, sua linha terminará com um espaço.
Pode ser mais confiável se você
--numstat
mesmo usar e calcular as estatísticas necessárias. Usar--numstat
(por exemplo, ingit log --numstat --pretty="@%ad" --date=short
) resulta em resultados como:Então você pode usar algo como o seguinte código awk:
Exemplo de saída:
Se quiser combinar as estatísticas de todos os commits no mesmo dia, você pode usar algo como:
Então:
Podemos inserir
0 insertions
depois de "alterado" se estiver faltando:Da mesma forma, podemos acrescentar,
0 deletions
se necessário:Roteiro completo
Canalize a saída
git log --pretty=%as --shortstat
para este pequeno programa (sem necessidade de@
formato outr
comandos):Usando uma única chamada para qualquer awk em qualquer shell em cada caixa Unix, isso
produzirá esta saída:
Aqui está uma versão comentada do script acima para ajudar a explicar o que ele faz:
Vejo pela sua resposta que você realmente deseja somar os valores por data - se sim, então isso, novamente usando any
awk
:produzirá esta saída:
sem ter que armazenar todos os valores na memória de uma só vez.
O acima pressupõe que isso:
produz uma saída como esta:
Solução completa baseada na regex do @meuh , mas ignorando a quantidade de arquivos alterados:
O
tail
comando da segunda linha é necessário para remover uma primeira linha vazia que astr
substituições introduzem na primeira linha.Depois disso, o
sed
comando remove tudo exceto data, linhas inseridas e linhas excluídas, contabilizando commits sem inserções ou exclusões.Em seguida, o
awk
comando soma a 2ª e a 3ª colunas agrupadas pela primeira coluna (data). Mas comoawk
as chaves do array não estão ordenadas, precisamos classificar o resultado com um finalsort
pela primeira coluna, o que produz a lista de estatísticas diárias exclusivas em ordem decrescente por data, por exemplo:Em Perl, isso seria relativamente simples, já que você pode usar a formatação inteira
%d
comprintf
, que imprimirá valores vazios como zeros, e/ou você pode usar o//
operador para definir um valor "padrão":ou com
s///e
, que permite código Perl na peça de substituição:Embora, como muru já mencionou, a saída de
--numstat
possa ser mais fácil de analisar.Por outro lado, pode ser mais fácil escolher cada valor separadamente, o que ajudaria a evitar o sangrento regex. Por exemplo, algo assim, que faz a soma diária ao mesmo tempo:
Aliás, isso é bastante fácil de ajustar para que
tr
não seja necessário, basta definir@
como separador de registros:(Observe que o
\s
seu regex é Perl-ismo. Embora o GNU o suporte por algum motivo, ele não é padrão e não é suportado pelas ferramentas padrão em outros sistemas.)