Git diff com números de linha (log Git com números de linha)

92

Quando faço a git diffou a git log -p, como obtenho os números das linhas do (s) arquivo (s) de origem alinhados com a saída?

Tentei pesquisar man git-diff | grep "line numbers"e pesquisar no Google, mas não obtive nada rapidamente.

Drew LeSueur
fonte

Respostas:

90

Você não pode obter números de linha legíveis com git diff

Atualmente não há opções para exibir os números das linhas verticalmente ao lado com git diff.

Formato de diff unificado

Essa informação está disponível nos (c) cabeçalhos de bloco para cada mudança no diff, porém, está apenas no formato de diff unificado :

@@ -start,count +start,count @@

O estado original do arquivo é representado com -, e o novo estado é representado com +(eles não significam adições e exclusões no cabeçalho do pedaço. startRepresenta o número da linha inicial de cada versão do arquivo e countrepresenta quantas linhas estão incluídas , começando do ponto inicial.

Exemplo

diff --git a/osx/.gitconfig b/osx/.gitconfig
index 4fd8f04..fcd220c 100644
--- a/osx/.gitconfig
+++ b/osx/.gitconfig
@@ -11,7 +11,7 @@ <== HERE!
 [color "branch"]
        upstream = cyan
 [color "diff"]
-       meta = yellow
+       meta = cyan
        plain = white dim
        old = red bold
        new = green bold

O cabeçalho do pedaço

@@ -11,7 +11,7 @@

diz que a versão anterior do arquivo começa na linha 11 e inclui 7 linhas:

11  [color "branch"]
12         upstream = cyan
13  [color "diff"]
14 -       meta = yellow
14 +       meta = cyan
15         plain = white dim
16         old = red bold
17         new = green bold

enquanto a próxima versão do arquivo também começa na linha 11 e também inclui 7 linhas.

O formato de diff unificado não é realmente para consumo humano

Como você provavelmente pode dizer, o formato de diff unificado não torna fácil descobrir os números das linhas (pelo menos se você não for uma máquina). Se você realmente deseja números de linha que possam ler, você precisará usar uma ferramenta de comparação que os exibirá para você.

Leitura Adicional

Khalid
fonte
3
Aqui está um grep para extrair apenas números de linha em arquivos modificados, por exemplo, para ser usado para filtrar um relatório de estilo de verificaçãogit diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
Jakub Bochenski
1
O comentário de @ JakubBochenski resolveu meu problema muito bem.
0xbe5077ed
Isso só é realmente útil se você especificar --unified=0ou -U0, no entanto.
caw
Acabei de terminar git diffn, uma substituição drop-in (invólucro) git diffque mostra números de linha e tem compatibilidade total com todos os usos e opções de git diff: stackoverflow.com/questions/24455377/…
Gabriel Staples
22

Aqui estão mais duas soluções, expandindo o código de Andy Talkowski.

Texto simples:

  git diff | gawk 'match($0,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
   /^(---|\+\+\+|[^-+ ])/{print;next};\
   {line=substr($0,2)};\
   /^-/{print "-" left++ ":" line;next};\
   /^[+]/{print "+" right++ ":" line;next};\
   {print "(" left++ "," right++ "):"line}'

Texto colorido, supondo que \033[66mseja o formato dos códigos de cores:

  git diff --color=always | \
    gawk '{bare=$0;gsub("\033[[][0-9]*m","",bare)};\
      match(bare,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
      bare ~ /^(---|\+\+\+|[^-+ ])/{print;next};\
      {line=gensub("^(\033[[][0-9]*m)?(.)","\\2\\1",1,$0)};\
      bare~/^-/{print "-"left++ ":" line;next};\
      bare~/^[+]/{print "+"right++ ":" line;next};\
      {print "("left++","right++"):"line;next}'

O código altera as linhas que começam com -e +para -1:-e +1:+, respectivamente, e as linhas que começam com nada para (5,6):. Os números são os números das linhas do respectivo arquivo.

PFudd
fonte
Percebo que ele quebra o alinhamento (indentação) do código, enquanto o nativo git diffmantém o alinhamento cuidadosamente. Este código está acima da minha cabeça no momento, então você estaria disposto a corrigi-lo? Em outras palavras, quando uma linha diz +240:+e a próxima diz (241,257):, você precisa adicionar alguns espaços extras à linha superior para fazer seu código manter o alinhamento e recuo adequados com o código da linha inferior. Talvez isso pudesse ser feito facilmente com impressão?
Gabriel Staples
... Quero dizer com printf.
Gabriel Staples
Deixa pra lá; Deixa comigo! Acabei de terminar git diffn. Veja aqui: stackoverflow.com/a/61997003/4561887 . Obrigado @PFudd, por sua resposta. Estudei e usei para aprender, então comecei do zero e escrevi git diffn. Uma vez formatado para que eu pudesse ler seu código (obrigado @EdMorton), pude aprender algumas coisas excelentes que me ajudaram.
Gabriel Staples
6

Aqui está um script que tenta consertar isso - não testei com raiva, mas parece ok. Ele se baseia nos registros que git diff produz e usa awk para manter contagens de linha.

# Massage the @@ counts so they are usable
function prep1() {
   cat | awk -F',' 'BEGIN { convert = 0; }
       /^@@ / { convert=1; }
       /^/  { if ( convert == 1 ) { print $1,$2,$3;
              } else { print $0;
              }
              convert=0;
             }'
}

# Extract all new changes added with the line count
function prep2() {
  cat | awk 'BEGIN { display=0; line=0; left=0; out=1;}
     /^@@ / { out=0; inc=0; line=$4; line--; display=line; left=line;        }
     /^[-]/   { left++; display=left; inc=0; }
     /^[+]/   { line++; display=line; inc=0; }
     /^[-+][-+][-+] / { out=0; inc=0; }
     /^/    { 
               line += inc;
               left += inc;
               display += inc;
               if ( out == 1 ) {
                   print display,$0;
               } else {
                   print $0;
               }
               out = 1;
               inc = 1;
               display = line;
            }'
} 

git diff $1 | prep1 | prep2 
Andy Talkowski
fonte
4

Você pode usar git difftoolpara fazer a comparação com um editor externo que exibirá os números das linhas. Veja como fazer isso com vim / vimdiff:

  1. Defina vimdiff como difftool do git:

    git config --global diff.tool vimdiff
    
  2. Configure ~/.vimrcpara mostrar automaticamente os números de linha ao usar o vimdiff:

    if &diff
        set number
    endif
    
  3. Execute git difftool, que usará vimdiff com números de linha:

    git difftool
    
wisbucky
fonte
Fazendo apenas git difftool, ele abriu para mim a ferramenta tkdiff, que por si só tem a função de número de linha. Obrigado, wisbucky
Richardd
3

Uma maneira rápida é usar git diff -U0. Isso definirá as linhas de contexto como 0, o que fará com que os valores @@ correspondam às linhas realmente alteradas. Por padrão, os valores @@ incluem 3 linhas de contexto antes / depois, o que não é conveniente para humanos.

Exemplo:

git diff # default
@@ -10,8 +10,8 @@

É difícil calcular os números das linhas alteradas porque a linha 10 se refere à primeira linha do contexto anterior. O número da linha real da primeira linha alterada é 10 + 3 = 13. Para calcular o número de linhas alteradas, você também deve subtrair o contexto antes e depois: 8-3-3 = 2.

git diff -U0
@@ -13,2 +13,2 @@

Como você pode ver, definir context = 0 torna os valores @@ mais fáceis de ler. Você pode ver que as linhas alteradas começam na linha 13 e há 2 linhas alteradas.

Isso não é perfeito, pois mostra apenas o número da linha de cada bloco. Se você quiser ver os números de cada linha, use o difftool para um editor externo. Consulte https://stackoverflow.com/a/50049752

wisbucky
fonte
3

Eu gosto de usar git difftoolcom fusão como o meu difftool. É mais fácil de olhar do que git diff, tem uma bela comparação de interface de usuário lado a lado e mostra os números das linhas em cada lado.

Configuração:

  1. Instruções sobre como configurar o meld como seu difftool para Windows ou Linux

Captura de tela de amostra:

insira a descrição da imagem aqui

Atualização de 24 de maio de 2020:

Recentemente, escrevi git diffnnos últimos dias para ser um substituto imediato para git diffa linha de comando. Dê uma chance. Veja minha outra resposta aqui .

Gabriel Staples
fonte
2

A partir de 24 de maio de 2020, você pode usar a ferramenta de terceiros git diffn(divulgação completa: eu a escrevi) para essa finalidade. É um invólucro leve git diff, escrito na awklinguagem de programação baseada em padrão / ação. Aqui está um exemplo de resultado da execução git diffn:

insira a descrição da imagem aqui

Aqui está uma demonstração:

1/3: Demonstração de git diffn:

Crie este arquivo:

hello_world.c:

#include <stdio.h>

int main()
{
    printf("Hello World\n");

    return 0;
}

Comprometa:

git add hello_world.c
git commit -m "add hello_world.c"

Altere para isto e salve o arquivo:

hello_world.c:

// Basic hello world example

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello Gabriel\n");
    
    int i = 700;
    printf("i = %i\n", i);
    return 0;
}

Agora execute:

git diff

Aqui está o resultado do git diffprimeiro para fins de comparação:

$ git diff
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+// Basic hello world example
+
 #include <stdio.h>
 
-int main()
+int main(int argc, char *argv[])
 {
-    printf("Hello World\n");
-
+    printf("Hello Gabriel\n");
+    
+    int i = 700;
+    printf("i = %i\n", i);
     return 0;
-}
\ No newline at end of file
+}

E uma captura de tela para mostrar a cor. Observe que a seção destacada em vermelho está simplesmente mostrando espaços em branco vazios (espaços neste caso) que podem ser excluídos:

insira a descrição da imagem aqui

Agora, aqui está o resultado de git diffn. Observe que ele mostra todos os números de linha perfeitamente!

  • Os números das linhas excluídas estão à esquerda e mostram um -sinal na extrema esquerda E à direita do :para ajudá-lo a ver melhor - se seus olhos gostam de escanear para a direita do cólon ou para baixo na extremidade esquerda da tela.
  • Os números das linhas adicionadas estão mais à direita e mostram um +sinal tanto na extrema esquerda quanto à direita de :.
  • Os números das linhas inalteradas mostradas para o contexto são mostrados tanto para a esquerda (arquivo antigo) quanto para a direita (novo arquivo), separados por um ,.

Saída de git diffn:

$ git diffn
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+        1:+// Basic hello world example
+        2:+
    1,   3: #include <stdio.h>
    2,   4: 
-   3     :-int main()
+        5:+int main(int argc, char *argv[])
    4,   6: {
-   5     :-    printf("Hello World\n");
-   6     :-
+        7:+    printf("Hello Gabriel\n");
+        8:+    
+        9:+    int i = 700;
+       10:+    printf("i = %i\n", i);
    7,  11:     return 0;
-   8     :-}
\ No newline at end of file
+       12:+}

E uma captura de tela para mostrar a cor. Observe que os dois pontos NÃO são coloridos ou estilizados para corresponder ao texto ao redor à esquerda e à direita. Este é um comportamento intencional e projetado para agir como um separador visual entre os números de linha adicionados à esquerda e a git diffsaída original à direita.

insira a descrição da imagem aqui

2/3: O que é?

Do topo degit-diffn.sh :

DESCRIÇÃO:

git-diffn.sh

  1. um substituto git diffinstantâneo para o qual também mostra a linha 'n' números! Use-o exatamente como git diff, exceto que você verá esses belos números de linha também para ajudá-lo a entender suas alterações.

  2. uma vez que é apenas um wrapper leve baseado em linguagem awk git diff, ele aceita TODAS as opções e parâmetros que git diffaceita. Exemplos:

  3. git diffn HEAD~

  4. git diffn HEAD~3..HEAD~2

  5. funciona com qualquer uma das suas git diffconfigurações de cor, mesmo se você estiver usando cores personalizadas

  6. Veja minha resposta aqui para saber como definir cores de diff personalizadas, bem como para ver uma captura de tela da saída de cor personalizada de git diffn: Como você personaliza a cor do cabeçalho diff no git diff?

  7. Aqui estão alguns exemplos de git configcomandos da minha resposta acima para definir git diffcores e atributos personalizados (formatação de texto):

       git config --global color.diff.meta "blue"
       git config --global color.diff.old "black red strike"
       git config --global color.diff.new "black green italic"
       git config --global color.diff.context "yellow bold"
    
  8. entrada git diffn, a saída de cores está ativada por padrão; se quiser desabilitar a cor de saída, você deve usar --no-colorou --color=never. Veja man git diffpara detalhes. Exemplos:

     git diffn --color=never HEAD~
     git diffn --no-color HEAD~3..HEAD~2
    

3/3: Instalação

  1. Windows (não testado): pode funcionar dentro do terminal bash que vem com o Git para Windows , mas não foi testado. Instale o Git para Windows. Abra o terminal bash que vem com ele e tente seguir as instruções abaixo. Eu preciso de alguns testadores que irão testar isso no Git para Windows. Consulte e responda aqui: https://github.com/git-for-windows/git/issues/2635 .
  2. Mac (não testado): use o terminal e siga as instruções abaixo. Você pode precisar instalar gawk. Se assim for, tente este : brew install gawk.
  3. Linux (testado no Ubuntu 18.04 e funciona perfeitamente): siga as instruções do terminal abaixo.

Opção 1 (minha recomendação): baixe todo o repo e, em seguida, crie um link simbólico para o programa para que você possa receber atualizações facilmente fazendo um a git pullpartir do repo sempre que quiser.

Primeiro, cdpara onde você deseja instalar isso. Então corra:

git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-diffn.sh" ~/bin/git-diffn

Feito! Agora basta fazer a etapa final abaixo!

Opção 2 (para quem quer apenas 1 arquivo): baixe apenas um arquivo uma vez.

mkdir -p ~/bin
cd ~/bin
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/git-diffn.sh
chmod +x git-diffn.sh
mv git-diffn.sh git-diffn

Feito! Agora basta fazer a etapa final abaixo!

Passo final:

Agora feche e reabra o seu terminal, ou re-fonte com . ~/.bashrc, e pronto!

git diffnagora funcionará como um substituto exato para o git diff!

Gabriel Staples
fonte
1

Podes tentar

git blame

no arquivo. Ele mostra o committer, o id do commit e o número da linha para cada linha no arquivo.

Juan
fonte
4
O problema com isso é que não mostra uma diferença , que é o que o autor do pôster original pediu. git blamemostrará apenas o estado atual do arquivo com os números das linhas.
5
Eu sabia sobre a culpa do git, mas alguém pesquisando no Google pode não ter. Isso pode ajudar alguém. Obrigado por responder.
Drew LeSueur
git blamede forma alguma responde à pergunta; Estou muito perplexo com os votos positivos aqui
Michael Mrozek
Não envie spam para o stackoverflow com respostas que não estejam relacionadas às perguntas.
Ahmed
0

Primeiro, configure sua ferramenta git diff, por exemplo, Meld

git config --global diff.tool meld

Em seguida, arranque seu difftool em algum arquivo:

git difftool -y config.rb

Lembre-se de definir o número da linha de acordo com a preferência da ferramenta diff.

HaxtraZ
fonte