Destacar linhas alteradas e bytes alterados em cada linha alterada

91

O projeto de código aberto Trac tem um excelente iluminador de diferenças - ele destaca as linhas alteradas e os bytes alterados em cada linha alterada! Veja aqui ou aqui para exemplos.

Existe uma maneira de usar o mesmo destaque de cor (ou seja, linhas alteradas e bytes alterados também ) no terminal bash,, gitou vim para saída diff (arquivo de patch)?

Nikolay Frantsev
fonte
O que você deseja destacar? Você quer uma ferramenta de comparação que destaque as mudanças de bytes? (isso seria muito útil). Você diz vim, pelo que me lembro, o vim já faz muita manipulação de cores quando você está usando modelos de linguagem de programação (e outros). Como você mudaria isso? Existem algumas técnicas disponíveis para alterar a cor em uma janela de terminal que é definida como VT100 (e existem dezenas de outras definições que também suportam sequências de escape de cor). Mais detalhes, por favor. Ou leia en.wikipedia.org/wiki/VT100 e links relacionados. Talvez isso possa ajudar.
Shellter
Eu sei que você está interessado apenas em ferramentas de código aberto, e apenas em terminal. Mas apenas como um ponto de referência, você pode querer dar uma olhada no diffzilla do slickedit. das poucas ferramentas de diff que usei, sempre pareceu representar melhor as diferenças de caracteres (embora definitivamente tivesse problemas quando as diferenças eram complexas (combinação de formatação e alterações de código, o que é sempre uma má ideia)
nhed
Parece uma cópia de stackoverflow.com/questions/3231759/…
Adam Monsen
Observação: o GitHub agora oferece essa ferramenta de comparação em sua interface web: stackoverflow.com/a/25723584/6309
VonC
Eu postei 'mais um' git puro, solução baseada em diff-realce com tutoriais para facilmente 1) encontrar o arquivo diff-realce relevante, 2) torná-lo executável 3) definir os parâmetros necessários em .gitconfig. Por favor, dê uma olhada. As instruções são para o Ubuntu 18.04, mas devem funcionar amplamente em sistemas Linux.
Zorglub29 01 de

Respostas:

57

O diff-highlightscript Perl contrib produz uma saída tão semelhante às capturas de tela do Trac que é provável que o Trac o esteja usando:

insira a descrição da imagem aqui

Instale com:

wget https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight && chmod +x diff-highlight

Mova o arquivo diff-highlightpara o ~/bin/diretório (ou onde quer que você $PATHesteja) e, em seguida, adicione o seguinte ao seu ~/.gitconfig:

[pager]
        diff = diff-highlight | less
        log = diff-highlight | less
        show = diff-highlight | less

Instalação de colagem de cópia única sugerida por @cirosantilli:

cd ~/bin
curl -O https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight
chmod +x diff-highlight
git config --global pager.log 'diff-highlight | less'
git config --global pager.show 'diff-highlight | less'
git config --global pager.diff 'diff-highlight | less'
Sina Samavati
fonte
Este. Isto e excelente. Obrigado. Parece ser um pouco conservador em alguns lugares, porém, faltando algumas linhas que obviamente têm uma grande parte do texto em comum. Você tem um rastreador de bug para isso?
naught101
20
Ah, isso é parte do git central agora: github.com/git/git/tree/master/contrib/diff-highlight
naught101
2
Agora foi transformado em um módulo, e acho que a versão mais fácil de baixar é a imediatamente anterior à mudança em raw.githubusercontent.com/git/git/…
Chris Midgley
4
Esta não é apenas parte do núcleo do git, ela é distribuída com o git e provavelmente já está no seu sistema. Adicionei detalhes sobre como ativá-lo em minha resposta abaixo. ↓
Cory Klein
1
Isso omite as diferenças que você vê por meio git add -p. Por favor, adicione também:git config --global interactive.diffFilter diff-highlight
josch
40

Enquanto estiver usando git diffou git loge possivelmente outros, use a opção --word-diff=color(também existem outros modos para diferenças de palavras BTW)

anydot
fonte
2
--word-diff=coloré realmente melhor (especialmente com git config color.diff.old "red reverse"e git config color.diff.new "green reverse"), mas não é o que eu quero :(
Nikolay Frantsev
4
Então, a única coisa que está faltando é marcar em cores / de alguma forma as linhas e bytes alterados ao mesmo tempo?
anydot
6
Quero destacar as linhas alteradas e os bytes alterados em cada linha alterada, como no Trac. Não apenas bytes alterados, não é o mesmo.
Nikolay Frantsev
Você também pode usar isso com git add --patch: stackoverflow.com/questions/10873882/…
naught101
A vantagem do diff-highlighté que funciona bem com diffs de palavras e diffs de linha.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
20

diff-so-fancyé um diff-highlighter projetado para olhos humanos.

Ele remove o +/ -que é irritante para recortar / colar e torna claras as seções entre os arquivos.

Colorido git(esquerda) x diff-so-fancy(direita - observe os destaques no nível do personagem):

saída tão extravagante

Se quiser a diff-so-fancysaída (lado direito), mas não restrita a arquivos em um gitrepositório, adicione a seguinte função ao seu .bashrcpara usá-la em qualquer arquivo:

dsf() { git diff --no-index --color "$@" | diff-so-fancy; }

Por exemplo:

dsf original changed-file

Destaque de nível de caractere e diffformato padrão

Se você não gosta da formatação fora do padrão diff-so-fancy, mas ainda deseja gitrealce no nível do caractere , use o diff-highlightque pegará gita saída de e produzirá uma diffsaída de formato padrão realmente bonita :

captura de tela diff-destaque

Para usá-lo por padrão git, adicione ao seu .gitconfig:

[color "diff-highlight"]
  oldNormal = red bold
  oldHighlight = red bold 52
  newNormal = green bold
  newHighlight = green bold 22

[pager]
  diff = diff-highlight | less -FRXsu --tabs=4

A [pager]seção diz gitpara canalizar sua saída já colorida para diff-highlightque colore no nível do caractere, e então pagina a saída em menos (se necessário), ao invés de apenas usar o padrão less.

Tom Hale
fonte
Isso é muito interessante, você poderia explicar um pouco sobre essas gitconfigopções?
caesarsol,
Atualizado, também adicionando função dsf().
Tom Hale
14

O comportamento que você deseja agora está disponível no próprio git (como foi apontado em um comentário por naught101). Para habilitá-lo, você precisa definir seu pager para

perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

onde /usr/share/doc/git/contrib/diff-highlight/diff-highlightestá a localização do script do marcador no Ubuntu 13.10 (não tenho ideia de por que está em uma docpasta). Se não estiver lá em seu sistema, tente usar locate diff-highlightpara encontrá-lo. Observe que o script de realce não é executável (pelo menos na minha máquina), daí o requisito para perl.

Para sempre usar o realce para os vários comandos do tipo diff, basta adicionar o seguinte ao seu ~/.gitconfigarquivo:

[pager]
    log = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    show = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    diff = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

Eu adicionei isso como uma nova resposta, o comentário de naught101 está enterrado e porque a configuração não é tão trivial quanto deveria ser e pelo menos na versão do Ubuntu que tenho as instruções no README não funcionam.

pastor
fonte
Acabei de notar que isso não ativa o destaque para os diffs dentro git add -p(modo interativo). Não sei como isso pode ser consertado, porém, simplesmente adicionar add à lista faz com que ele trave.
dshepherd,
5
Isso deve funcionar agora no git 2.9.0:git config interactive.diffFilter diff-highlight
Thomas
^ Isso! Infelizmente, diff-highlightnão estava no meu caminho, então tive que localizá-lo primeiro. Detalhes na minha resposta abaixo.
Cory Klein
11

Um utilitário para diffs baseado em bytes foi distribuído com o Git oficial desde v1.7.8 1 . Você só precisa localizar onde está instalado em sua máquina e habilitá-lo.

Descubra onde o Git está instalado

  • MacOS com Git instalado via Homebrew : é/usr/local/opt/git
  • Windows com Git para Windows : Execute cd / && pwd -Wpara localizar o diretório de instalação.
  • Linux: Nerd. Se você ainda não sabe onde o Git está instalado, então ll $(which git)ou locate gitdeve ajudar.

Link diff-highlightpara o diretório bin para que seu PATH possa encontrá-lo

GIT_HOME='/usr/local/opt/git/'  # Use the value from the first step.
ln -s "${GIT_HOME}/share/git-core/contrib/diff-highlight/diff-highlight" \
      '/usr/local/bin/diff-highlight'

Habilite em sua configuração Git

git config --global interactive.diffFilter diff-highlight # Use on interactive prompts
git config --global pager.diff "diff-highlight | less"    # Use on git diff
git config --global pager.log  "diff-highlight | less"    # Use on git log
git config --global pager.show "diff-highlight | less"    # Use on git show

1 Aqui está a versão v1.7.8 , mas muitas mudanças foram feitas desde então.

Cory Klein
fonte
1
Seria bom especificar em qual versão ele começou a ser distribuído com o git. Também estou supondo que as distros irão colocá-lo no PATH por padrão, então a etapa do link simbólico não será necessária? E which gitrequer que esteja no PATH em primeiro lugar, então não funcionará se não estiver :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
Seria bom! Sinta-se à vontade para adicionar essas informações. E embora o Git empacote diff-highlight, na verdade não o instala , então a etapa do link simbólico é realmente necessária (pelo menos no macOS). Se você achar que não é necessário para sua plataforma, fique à vontade para atualizar a resposta novamente. Enquanto isso, which gitnormalmente não funciona, porque o Git faz instalar a gitalgum lugar binário no caminho.
Cory Klein
Note que no debian unstable eu precisei "compilar" este arquivo, porque eu só tinha um .perl. A compilação é trivial: basta executar sudo makeno diff-highlightdiretório.
tobiasBora 01 de
10

Eu uso a --color-wordsopção e funciona bem para mim:

$ git diff --color-words | less -RS
amizado
fonte
5
Não, isso mostra a diferença nas palavras. O que o OP (e eu) queremos é uma diferença normal linha por linha, com as diferenças de palavras destacadas (então, digamos que as linhas diferentes são texto colorido e as diferenças de palavras dentro dessas linhas são texto colorido normal, com destaque colorido ou alguma coisa). Veja os links de exemplo agora na pergunta.
naught101
1
pastebin.com/1JrhYHRt Na verdade, eu uso vimdiff como difftool e vimdiff com molokai colorscheme para obter um bom destaque conforme você descreve em sua pergunta. 1- git config --global diff.tool vimdiff 2- in vim ": colo molokai" * Molokai @ github.com/tomasr/molokai * Possível esquema de cores automático com ~ / .vimrc: if & diff set background = dark colorscheme molokai endif
amized
4

como @dshepherd diz :

O comportamento que você deseja agora está disponível no próprio git

Mas diff-highlightestá localizado no DOC e não está disponível no shell.
Para instalar diff-highlightem seu ~/bindiretório, siga as próximas etapas (isso salvará sua digitação):

$ locate diff-highlight
$ cd /usr/share/doc/git/contrib/diff-highlight  #or path you locate
$ sudo make
$ mv diff-highlight ~/bin

Em seguida, configure seu .gitconfigcomo documento oficial diz:

[pager]
    log  = diff-highlight | less
    show = diff-highlight | less
    diff = diff-highlight | less

UPD
Além disso, você pode tentar o próximo no último gitsem qualquer instalação:

git diff --color-words=.

Mais complexo:

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eugen Konkov
fonte
1

O Emacs tem a função ediff-patch-buffer que deve atender às suas necessidades.

Abra o arquivo sem patch no emacs digite ESC-x, ediff-patch-buffer.

Siga as instruções e você verá uma comparação destacada das versões com patch e original do seu arquivo.

De acordo com seu comentário, o seguinte fornecerá uma solução bash que requer apenas dwdiff:

#!/bin/bash
paste -d'\n' <(dwdiff -2 -L -c <(cat $2) <(patch $2 -i $1 -o -)) <(dwdiff -1 -L -c <(cat $2) <(patch $2 -i $1 -o -))| uniq
Finbar Crago
fonte
desculpe, eu não quero usar emacs, apenas bash, git ou vim
Nikolay Frantsev
Isso é compreensível. A única outra coisa que posso pensar é em usar o colordiff com o stdout do patch: colordiff -u <(patch original_file -i patch_file -o -) <(cat original_file) mas isso só vai destacar as linhas alteradas, não as mordidas ...
Finbar Crago
Pensei um pouco mais no seu problema e acrescentei uma segunda solução que requer apenas dwdiff.
Finbar Crago
1
por favor, leia atentamente minha pergunta, eu não quero comparar arquivos
Nikolay Frantsev
1
desculpe pela confusão, então você está atrás de uma maneira de destacar os bytes alterados nas linhas alteradas de um arquivo diff? se sim, tentedwdiff -c --diff-input diff_file
Finbar Crago
1

Diffy

GitLab está usando Diffy https://github.com/samg/diffy (Ruby) para obter uma saída semelhante ao GitHub e diff-highlight:

insira a descrição da imagem aqui

O Diffy faz o próprio diff usando o mesmo algoritmo do Git e oferece suporte a diferentes tipos de saídas, incluindo a saída HTML que o GitLab usa:

gem install diffy
echo '
  require "diffy"    
  puts Diffy::Diff.new("a b c\n", "a B c\n").to_s(:html)
' | ruby

Resultado:

<div class="diff">
  <ul>
    <li class="del"><del>a <strong>b</strong> c</del></li>
    <li class="ins"><ins>a <strong>B</strong> c</ins></li>
  </ul>
</div>

Observe como strongfoi adicionado aos bytes alterados.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
0

Sim, o Vim faz isso incluindo o destaque do texto alterado dentro de uma linha.
Veja :h diffe :h 08.7para mais detalhes sobre como comparar arquivos.

O Vim usa um algoritmo bastante simples para realçar. Ele procura na linha o primeiro caractere alterado e, em seguida, o último caractere alterado, e simplesmente destaca todos os caracteres entre eles.
Isso significa que você não pode ter vários destaques por linha - muitas decisões de design no Vim priorizam a eficiência.

PDug
fonte
infelizmente, ele não destaca os bytes alterados na saída do diff (definir tipo de arquivo = diff)
Nikolay Frantsev
1
Acho que entendi sua pergunta agora - você deseja destacar a sintaxe da saída textual do comando diff para que ele destaque todas as alterações feitas dentro de uma linha. Editar este texto no Vim destaca as diferenças de linha, mas não as alterações feitas dentro de uma linha.
PDug
Você poderia usar o comando: patchfile do Vim para carregar o arquivo original e depois compará-lo com a versão corrigida?
PDug
infelizmente não, quero usar a saída diff recursiva para vários arquivos
Nikolay Frantsev
0

vimdiff file1 file2 irá mostrar a diferença entre dois arquivos.

vimdiff é uma ferramenta diff incluída no vim. (O Vim deveria ter sido compilado com a opção + diff, para ter certeza de que você pode verificar :version)

Você também pode iniciá-lo de dentro do vim. Veja :help diffpara mais informações e comandos.

Xavier T.
fonte
Não quero comparar arquivos, quero destacar o arquivo diff (patch).
Nikolay Frantsev
@Nikolay Frantsev Se você não se preocupa com desempenho, pode instalar meu plugin format.vim e fazer vimdiff file.old file.new -c 'FormatCommand diffformat' -c 'w! file.diff.html' -c 'qa!'.
ZyX
Ele fará uma comparação em um modo de lote (prefixar screen -D -mou acrescentar &>/dev/null(a variante / dev / null às vezes produz bugs estranhos) se você não quiser ver o terminal piscando) e sair do vim após a formatação, mas é puro vimscript e mesmo com minhas otimizações, é muito lento para arquivos grandes.
ZyX
0

Nota : esta é uma duplicata do que é encontrado aqui: Como melhorar o realce de diff do git?. Postando minha resposta aqui também, pois pode ser útil para algumas pessoas que encontram este tópico diretamente :)

Como dito em algumas respostas anteriores, isso é possível apenas com o material git. Eu posto isso porque as instruções podem ser um pouco mais fáceis de seguir dependendo do seu sistema, mas isso é semelhante a várias outras respostas.

Uma solução que depende puramente do git e de seus contributos. Isso não requer nenhum arquivo adicional do que o git . Todas as explicações são para o Ubuntu (testado em 18.04LTS), deve funcionar da mesma forma em outros sistemas Linux:

  • Localize o snippet contrib git diff-realce:
find -L /usr -name diff-highlight -type f

no meu sistema, a única resposta válida é:

/usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Torne o script perl correspondente executável. No meu caso, eu precisava fazer:
sudo chmod +x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Atualize seu ~/.gitconfigpara obter o resultado desejado, adicionando (observe que são TABS, não 4 espaços):
[color "diff-highlight"]
    oldNormal = red
    oldHighlight = red 52
    newNormal = green
    newHighlight = green 22
  • Aproveite o resultado (nota: isso é apenas para a coloração diff + destaque, tenho outras coisas em jogo aqui também para o prompt, é claro :)).

diff-highligh

Zorglub29
fonte