Git diff para mostrar apenas as linhas que foram modificadas

128

Quando eu faço um diff do git, ele mostra as linhas que foram adicionadas:

+ this line is added

linhas que foram removidas:

- this line is removed

mas também mostra muitas linhas que não são modificadas:

this line is not modified
this line is also not modified

Isso resulta no diff real do git parecido com este:

+ this line is added
  this line is not modified
- this line is removed
  this line is not modified

Posso pedir ao git para mostrar apenas as linhas que foram modificadas e ignorar todos os outros códigos que não foram modificados? Eu escrevi um método que removerá todas as linhas que não têm um sinal de "+" ou "-" na frente delas, mas tenho certeza de que deve haver uma maneira mais simples de fazer isso.

No meu git diff, estou interessado apenas em ver as linhas que foram modificadas.

Desde já, obrigado.

r3b00t
fonte

Respostas:

182

O que você quer é um diff com 0 linhas de contexto. Você pode gerar isso com:

git diff --unified=0

ou

git diff -U0

Você também pode definir isso como uma opção de configuração para esse repositório:

git config diff.context 0

Para configurá-lo globalmente, para qualquer repositório:

 git config --global diff.context 0
Chris Hayes
fonte
4
Obrigado pela resposta rápida. Isso resolve metade do meu problema, mas ainda estou recebendo algumas linhas como "@@ -1 +1 @@" no meu diff e a parte superior do meu diff git tem "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t
3
Eu não acho que o git forneça nenhuma maneira de evitar a saída dessas linhas, porque o diff não faria sentido sem elas (você não poderia saber qual arquivo estava vendo, nem onde estava no arquivo).
precisa saber é o seguinte
8
@Rakesh: Para expandir, o git-diff tenta criar diffs que podem realmente ser usados ​​como patches nos arquivos de origem, o que é impossível sem essas informações. A única maneira de removê-lo seria pós-processá-lo você mesmo, como via git diff | egrep "^(\+|-) ".
Chris Hayes
1
git config --global diff.context 0 para tê-lo definido globalmente
Andrzej Rehmann
Se você quiser ver em uma determinada tentativa diretório git diff -U0 <dir>
Eswar Yaganti
41

Outro hack (em un * x) para mostrar apenas as linhas que começam com +e -:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

O código acima faz o seguinte:

  • git diff -U0: escolha 0 linhas de contexto
  • O primeiro grep inclui apenas todas as linhas que começam com +ou-
  • O segundo grep exclui linhas que começam com --- a/ou+++ b/

Cor

Para mostrar diferenças coloridas, tente o seguinte:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • A expressão, ^\e\[[^m]*m[-+]procura o início da linha ( ^), o caractere de escape ( \e) seguido pelo [qual juntos iniciam a sequência de escape e, em seguida, qualquer caractere que não seja um "m" (números, ponto-e-vírgula ou nada), seguido por um " m "que termina a sequência de escape.
  • Observe que todas as seguintes são seqüências de escape válidas: \e[0m(redefinir), \e[m(também redefinir), \e[1m(negrito ativado), \e[31m(vermelho), \e[32m(verde), \e[9;31m(riscar + vermelho), \e[31;9m(vermelho + riscar), \e[1;4;9;31m(negrito + sublinhado + riscar + vermelho). As cores padrão do git usam vermelho e verde, mas podem ser reconfiguradas.
  • --coloré o mesmo que --color=always.
  • A restrição --- a/ou +++ b/a aparecer no início da linha foi removida para acomodar as seqüências de escape e isso pode levar a um caso extremo.

Notas Adicionais:

  • A solução acima precisa ser modificado se você usar opções adicionais git diff tais como -R, --src-prefix, --dst-prefix, --no-prefix, etc.
  • Os dois greps podem ser combinados em um único grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', mas acho a versão do grep duplo mais fácil de entender.
user650654
fonte
2
Agradável. Voto positivo para uma explicação clara de cada filtro.
precisa saber é o seguinte
Eu vejo muitas git difflinhas do tipo "cabeçalho" que começam com @@, mas o que são git difflinhas que começam com ---ou +++? Eu não estava ciente desses.
Gabriel Staples
Ah deixa pra lá. Esses denotam nomes de arquivos para arquivos que contêm adições ( +++) ou exclusões ( ---). Vejo isso aqui agora: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples
Correção mais uma vez: --- a/filenameparece indicar o "arquivo à esquerda" ou o arquivo como era antes e +++ b/filenameparece indicar o "arquivo à direita" ou o arquivo como está agora com suas alterações. Estou tão acostumado a usar o git difftoolmeld , que mostra belas comparações lado a lado, que nunca me acostumei a olhar git diff, então ainda me parece estranho, e nunca olhei essas nuances antes.
Gabriel Staples
1
@ GabrielStaples, foi adicionado suporte para cores. Obrigado.
user650654
6

Após o comentário mais recente de Chris, o principal problema com o pós-processamento é que você deseja manter as linhas começando, -|+mas também deseja filtrar as que começam com ---|+++. Se você estiver armazenando arquivos de correção no seu repositório (eu faço, no Pydoop ), por outro lado, você deseja manter as linhas que começam com --|++, para que o regexp se torne um pouco envolvido:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

O regexp usa uma aparência negativa: consulte a resposta de Peter Boughton para esta pergunta para obter uma explicação detalhada.

Se você fizer isso com frequência, convém configurar um alias para o git:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'
simleo
fonte
1
isso não funcionou para mim no Windows git bash. Não sei por que (grep disse a opção inválida P), não tem coragem de investigar isso no momento.
Dennis
1
-Pou --perl-regexpé usado para interpretar o padrão como uma repressão regular do Perl, mas nem sempre é implementado. Não funcionou para mim no OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega
5

Eu acho que, para casos simples, a regex pode ser muito mais curta e fácil de lembrar, com a ressalva de que isso não funcionará se você tiver alterações de linha onde a própria linha começa com +ou-

$ git diff | grep '^[+|-][^+|-]'

O regex diz que a linha deve começar com +ou -, e o caractere imediatamente seguinte não deve ser nenhum deles. Eu obtive os mesmos resultados, se eu escapei do +aqui ou não, aliás ...


Exemplo:

$ cat testfile
A
B
C
D
E
F
G

Digamos que eu mude Cpara X, Epara Ye Gpara Z.

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

Como eu disse acima, porém, isso é apenas para a maioria dos casos. Se você canalizar essa saída para um arquivo dout, tente o mesmo regex, ele não funcionará.

$ git diff dout | grep '^[+|-][^+|-]'
$

De qualquer forma, espero que ajude no seu caso

Galois
fonte
Nos casos em que a linha começa com "-", ela não funciona. Exemplo: - name: No pdbem um arquivo yaml.
Anapaulagomes
3

Esta resposta manterá as cores vermelho / verde originais para facilitar a leitura. Forneci algumas variações na sintaxe:

git diff --color | grep --color=never $'^\e\[3[12]m'
git diff --color | grep --color=never $'^\033\[3[12]m'
git diff --color | grep --color=never -P '^\e\[3[12]m'
git diff --color | grep --color=never -P '^\033\[3[12]m'

Explicação:

  • O git diff --coloré necessário para evitar git desabilitem a cor quando ele é tubulação.
  • A grep --color=neveré para evitar grep remover a cor original e destacando o texto correspondente.
  • Estamos correspondendo a linhas que começam com códigos de escape vermelhos ( \e[31m) ou verdes ( \e[32m).
  • A $'...'(sintaxe ANSI-C entre aspas) ou -P(sintaxe perl) deve grepser interpretada \eou \033como um ESCcaractere.
wisbucky
fonte
Obrigado por isso. Aqui está uma forma alternativa que acabei de criar. Sua $''parte me ajudou especialmente. stackoverflow.com/a/61929887/4561887
Gabriel Staples
1

Como usar awkpara mostrar apenas as linhas +e -, respondendo por qualquer forma de cor ou texto, git diffpode estar gerando:

Nenhuma das outras respostas aqui (incluindo minha outra resposta ) fará exatamente o que você deseja 100% corretamente. Esta resposta, no entanto, será. Aqui está um liner que você pode copiar e colar no seu terminal. Acabei de criar várias linhas para facilitar a leitura - você pode copiar e colar da mesma maneira para que eu possa torná-lo legível! Ele se baseia na awklinguagem de programação:

git diff --color=always "$@" | awk '
# 1. Match and then skip "--- a/" and "+++ b/" lines
/^(\033\[(([0-9]{1,2};?){1,10})m)?(--- a\/|\+\+\+ b\/)/ {
    next 
} 
# 2. Now print the remaining "+" and "-" lines ONLY! Note: doing step 1 above first was required or
# else those lines would have been matched by this matcher below too since they also begin with 
# the "+" and "-" symbols.
/^(\033\[(([0-9]{1,2};?){1,10})m)?[-+]/ {
    print $0 
}
' | less -RFX

Aqui estão suas características. Todos esses recursos, quando considerados em conjunto, resolvem as deficiências de todas as outras respostas aqui:

  1. Ele lida com saída colorida e sem cores. É isso que essa expressão regular faz:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Ele lida com TODAS AS CORES e TODAS AS OPÇÕES DE FORMATAÇÃO DE TEXTO, incluindo negrito, itálico, tachado, etc., que você pode definir nas suas git configconfigurações . É por isso que o regex acima tem ;?e {1,10}nele: se detectar o início de uma cor ou código de formatação de texto, ele irá corresponder a até 10 seqüências de estes códigos ANSI combinados.
  3. NÃO inclui também linhas que começam com @@a palavra diff, como a resposta aceita . Se você deseja essas linhas (que, francamente, acho úteis) :), faça o seguinte:

    git diff --unified=0
    

    ou

    git diff -U0
    
  4. Ele mostra a saída da mesma maneira exata que git difffaria: no lesspager com saída em cores opcional ( -R), e somente se o texto for> 1 página ( -F), e mantendo a página atual do texto na tela quando você qusar ( -X) .

Ele também tem o benefício de ser poderoso e facilmente configurável, pois usa a linguagem de programação awk.

Se você estiver interessado em aprender o awk , veja alguns recursos:

  1. gawkawkManual (GNU ): https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Estudo git diffne comentários: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Se você quiser git diffntambém, que é git diffcom números de linha, veja aqui: Git diff com números de linha (log do Git com números de linha)
  3. Alguns exemplos de teste do awk "olá mundo" e de sintaxe: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Como bônus, também git diffcencerrei o item acima para ser usado como , o que significa "git diff para mostrar SOMENTE 'mudanças'". O uso é idêntico a git diff; basta usar git diffc! Ele suporta TODAS as opções. A cor está ativada por padrão. Para desligá-lo, basta usar git diffc --no-colorou git diffc --color=never. Veja man git diffpara detalhes.

Desde que eu terminei git diffn(uma ferramenta para mostrar git diffcom números e linhas) ontem à noite, a escrita git diffcfoi trivial. Achei melhor fazê-lo agora enquanto o conhecimento está fresco na minha cabeça.

Instalar git diffc:

Siga as instruções no final desta resposta aqui , exceto em todos os lugares que você vê git-diffnnas instruções, use em seu git-diffclugar. Isso inclui também no wgetcomando. Baixar e instalar git diffcé fácil: são apenas alguns comandos.

Gabriel Staples
fonte
0

Aqui está outra maneira mais simples de encontrar apenas as linhas que foram modificadas e, portanto, começam com uma única +ou -, mantendo a saída colorida:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. O -U0diz para incluir 0 linhas de contexto em torno das linhas alteradas - ou seja: incluem apenas os próprios linhas alteradas. Veja man git diff.
  2. O -Efor grep permite trabalhar com expressões regulares estendidas
  3. A $''sintaxe aparentemente permite a citação ANSI, que interpreta corretamente o caractere ESC (escape ou 0x1b) corretamente. Veja aqui .
  4. E aqui está a descrição da regex em https://www.regex101.com :insira a descrição da imagem aqui
  5. Basicamente, ^corresponde ao início da linha, \ecorresponde ao caractere Escape, que é o início de um código de cores no terminal, \[corresponde ao próximo caractere no código de cores, que é [, e a (this|that)sintaxe corresponde a "this" ou "that" , onde "this" é 32m+, que é uma linha verde + e 31m-é uma linha vermelha.
  6. As cores são assim: \e[32mé verde e \e[31mvermelho.
  7. +mostra as linhas marcadas git diffcomo adicionadas, é claro, e -mostra as linhas marcadas git diffcomo excluídas.
  8. Observe que isso --color=neveré necessário na 2ª grepexpressão para impedir que ela destaque suas correspondências, o que de outra forma danificaria os códigos de cores vindos git diffda esquerda.
  9. Ele +também deve ser escapado, \+porque, caso contrário, +é um caractere de expressão regular especial (regex) que especifica uma ou mais ocorrências do elemento anterior . Veja aqui: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Referências:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Responder por @ user650654: Git diff para mostrar apenas as linhas que foram modificadas
  3. Responder por @wisbucky: Git diff para mostrar apenas as linhas que foram modificadas

Palavras-chave:

  1. [minha própria resposta] Git diff com números de linha (log Git com números de linha)
  2. [resposta de outra pessoa] Git diff com números de linha (log do Git com números de linha)
  3. git diff com números de linha e alinhamento / recuo de código adequado
  4. git-filechange-search.sh- um script que permite procurar um arquivo por um nome de variável ou função e descobrir quais confirmações contêm alterações nesse nome de variável ou função. Ex. use : ./git-filechange-search.sh path/to/my/file.cpp variable_nameencontrará todas as confirmações com alterações em file.cpp que contêm variable_namenelas. Isso é útil para ver onde e quando determinados recursos foram alterados. É como se fosse uma pesquisa que pudesse observar seções de um arquivo exibidas ao git blamelongo do tempo.
Gabriel Staples
fonte