git-diff para ignorar ^ M

Em um projeto em que alguns dos arquivos contêm ^ M como separadores de nova linha. Diffing esses arquivos são aparentemente impossíveis, já que o gitdiff vê como o arquivo inteiro é apenas uma linha.

Como se diferencia com a versão anterior?

Existe uma opção como “tratar ^ M como nova linha ao diferenciar”?

prompt> git-diff "HEAD^" -- MyFile.as diff --git a/myproject/MyFile.as b/myproject/MyFile.as index be78321..a393ba3 100644 --- a/myproject/MyFile.cpp +++ b/myproject/MyFile.cpp @@ -1 +1 @@ -import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate \ No newline at end of file +import flash.events.MouseEvent;^Mimport mx.controls.*;^Mimport mx.utils.Delegate \ No newline at end of file prompt> 

ATUALIZAR:

agora eu escrevi um script que verifica as últimas 10 revisões e converte CR para LF.

 require 'fileutils' if ARGV.size != 3 puts "a git-path must be provided" puts "a filename must be provided" puts "a result-dir must be provided" puts "example:" puts "ruby gitcrdiff.rb project/dir1/dir2/dir3/ SomeFile.cpp tmp_somefile" exit(1) end gitpath = ARGV[0] filename = ARGV[1] resultdir = ARGV[2] unless FileTest.exist?(".git") puts "this command must be run in the same dir as where .git resides" exit(1) end if FileTest.exist?(resultdir) puts "the result dir must not exist" exit(1) end FileUtils.mkdir(resultdir) 10.times do |i| revision = "^" * i cmd = "git show HEAD#{revision}:#{gitpath}#{filename} | tr '\\r' '\\n' > #{resultdir}/#{filename}_rev#{i}" puts cmd system cmd end 

O GitHub sugere que você deve usar somente \ n como um caractere de nova linha em repositorys tratados com git. Há uma opção para converter automaticamente:

 $ git config --global core.autocrlf true 

Claro, isso é dito para converter crlf para lf, enquanto você deseja converter cr para lf. Espero que isso ainda funcione …

E então converta seus arquivos:

 # Remove everything from the index $ git rm --cached -r . # Re-add all the deleted files to the index # You should get lots of messages like: "warning: CRLF will be replaced by LF in ." $ git diff --cached --name-only -z | xargs -0 git add # Commit $ git commit -m "Fix CRLF" 

core.autocrlf é descrito na página man .

Desenvolvendo no Windows, me deparei com esse problema ao usar o git tfs . Eu resolvi assim:

 git config --global core.whitespace cr-at-eol 

Isso basicamente diz ao Git que um CR de final de linha não é um erro. Como resultado, esses caracteres irritantes não aparecem mais no final das linhas em git diff , git show , etc.

Parece deixar outras configurações como estão; por exemplo, espaços extras no final de uma linha ainda são mostrados como erros (destacados em vermelho) no diff.

(Outras respostas aludiram a isso, mas o acima é exatamente como definir a configuração. Para definir a configuração para apenas um projeto, omita o --global .)

EDITAR :

Depois de muitas dificuldades de finalização de linha, tive a melhor sorte, ao trabalhar em uma equipe do .NET, com essas configurações:

  • NENHUMA configuração core.eol
  • NÃO configuração core.whitespace
  • NENHUM ajuste do core.autocrlf
  • Ao executar o instalador do Git para Windows, você terá estas três opções:
    • Finalize o estilo Windows, confirme os finais de linha no estilo Unix <- escolha este
    • Faça o check-out no estado em que se encontra, confirme os finais de linha no estilo Unix
    • Finalizar como está, confirmar como está

Se você precisar usar a configuração de espaço em branco, provavelmente deverá ativá-la apenas por projeto se precisar interagir com o TFS. Apenas omita o --global :

 git config core.whitespace cr-at-eol 

Se você precisar remover algumas configurações do core. *, A maneira mais fácil é executar este comando:

 git config --global -e 

Isso abre seu arquivo .gitconfig global em um editor de texto e você pode excluir facilmente as linhas que deseja remover. (Ou você pode colocar ‘#’ na frente deles para comentá-los).

Experimente o git diff --ignore-space-at-eol , ou git diff --ignore-space-change , ou git diff --ignore-all-space .

Veja também:

 core.whitespace = cr-at-eol 

ou equivalente,

 [core] whitespace = cr-at-eol 

onde o whitespace em whitespace é precedido por um caractere de tabulação .

Por que você pega esses ^M no seu git diff ?

No meu caso eu estava trabalhando em um projeto que foi desenvolvido no Windows e usei o OS X. Quando mudei algum código, vi ^M no final das linhas que adicionei no git diff . Eu acho que o ^M estava aparecendo porque eles eram finais de linha diferentes do que o resto do arquivo. Como o restante do arquivo foi desenvolvido no Windows, ele usava terminações de linha CR e, no OS X, usa terminais de linha LF .

Aparentemente, o desenvolvedor do Windows não usou a opção ” Finalizar o estilo do Windows, comprometer terminações de linha no estilo Unix ” durante a instalação do Git.

Então, o que devemos fazer sobre isso?

Você pode fazer com que os usuários do Windows reinstalem o git e usem a opção ” Finalizar o estilo do Windows, consolidar terminações de linha no estilo Unix “. Isso é o que eu preferiria, porque vejo o Windows como uma exceção em seus caracteres de término de linha e o Windows corrige seu próprio problema dessa maneira.

Se você optar por essa opção, deverá, no entanto, corrigir os arquivos atuais (porque eles ainda estão usando as terminações de linha CR ). Eu fiz isso seguindo estes passos:

  1. Remova todos os arquivos do repository, mas não do seu sistema de arquivos.

     git rm --cached -r . 
  2. Adicione um arquivo .gitattributes que .gitattributes determinados arquivos para usar um LF como final de linha. Coloque isso no arquivo:

     *.ext text eol=crlf 

    Substitua .ext pelas extensões de arquivo que você deseja corresponder.

  3. Adicione todos os arquivos novamente.

     git add . 

    Isso mostrará mensagens como esta:

     warning: CRLF will be replaced by LF in . The file will have its original line endings in your working directory. 
  4. Você pode remover o arquivo .gitattributes menos que tenha usuários teimosos do Windows que não queiram usar a opção “Fazer check-out no estilo do Windows, consolidar terminações de linha no estilo Unix “.

  5. Comprometer e empurrar tudo.

  6. Remova e registre os arquivos aplicáveis ​​em todos os sistemas em que eles são usados. Nos sistemas Windows, certifique-se de que eles agora usam a opção “Fazer check-out no estilo do Windows, consolidar terminações de linha no estilo Unix “. Você também deve fazer isso no sistema onde você executou essas tarefas, porque quando você adicionou os arquivos git disse:

     The file will have its original line endings in your working directory. 

    Você pode fazer algo assim para remover os arquivos:

     git ls | grep ".ext$" | xargs rm -f 

    E então isso para recuperá-los com os finais de linha corretos:

     git ls | grep ".ext$" | xargs git checkout 

    É claro que substituindo .ext pela extensão desejada.

Agora seu projeto usa apenas caracteres LF para os finais de linha, e os personagens desagradáveis ​​de CR nunca mais voltarão :).

A outra opção é impor finais de linha no estilo do Windows. Você também pode usar o arquivo .gitattributes para isso.

Mais informações: https://help.github.com/articles/dealing-with-line-endings/#platform-all

Existe uma opção como “tratar ^ M como nova linha ao diferenciar”?

Haverá um com o Git 2.16 (Q1 2018), pois a família de comandos ” diff ” aprendeu a ignorar as diferenças no retorno do carro no final da linha.

Veja commit e9282f0 (26 out 2017) de Junio ​​C Hamano ( gitster ) .
Ajudado por: Johannes Schindelin ( dscho ) .
(Mesclado por Junio ​​C Hamano – gitster – em commit 10f65c2 , 27 nov 2017)

diff: --ignore-cr-at-eol

Uma nova opção --ignore-cr-at-eol diz ao mecanismo de diferenças para tratar um retorno de carro no final de uma linha (completa) como se ela não existisse.

Assim como outras opções ” --ignore-* ” para ignorar vários tipos de diferenças de espaço em branco, isso ajudará a rever as mudanças reais que você fez sem se distrair com a falsa conversão CRLF<->LF feita pelo seu programa de edição.

Eu lutei com esse problema por um longo tempo. De longe, a solução mais fácil é não se preocupar com os caracteres ^ M e apenas usar uma ferramenta de comparação visual que possa lidar com eles.

Em vez de digitar:

 git diff   

experimentar:

 git difftool   

TL; DR

Altere o core.pager para "tr -d '\r' | less -REX" , não o código-fonte

Isso é por que

Aqueles incômodos ^ M mostrados são um artefato da colorização e do pager. insira a descrição da imagem aqui É causado por less -R , uma opção de pager git padrão. (pager padrão do git é less -REX )

A primeira coisa a notar é que o git diff -b não mostrará as mudanças no espaço em branco (por exemplo, o \ r \ n vs \ n)

configuração:

 git clone https://github.com/CipherShed/CipherShed cd CipherShed 

Um teste rápido para criar um arquivo unix e alterar os finais de linha não mostrará alterações com git diff -b :

 echo -e 'The quick brown fox\njumped over the lazy\ndogs.' > test.txt git add test.txt unix2dos.exe test.txt git diff -b test.txt 

Notamos que forçar um pipe para menos não mostra o ^ M, mas ativando a cor e less -R :

 git diff origin/v0.7.4.0 origin/v0.7.4.1 | less git -c color.ui=always diff origin/v0.7.4.0 origin/v0.7.4.1 | less -R 

A correção é mostrada usando um pipe para retirar o \ r (^ M) da saída:

 git diff origin/v0.7.4.0 origin/v0.7.4.1 git -c core.pager="tr -d '\r' | less -REX" diff origin/v0.7.4.0 origin/v0.7.4.1 

Uma alternativa insensata é usar less -r , porque ele passará por todos os códigos de controle, não apenas pelos códigos de colors.

Se você quer apenas editar seu arquivo de configuração do git diretamente, esta é a input para atualizar / adicionar:

 [core] pager = tr -d '\\r' | less -REX 

Se você estiver usando o Eclipse, você pode fazer o ^M desaparecer do git diff definindo File > Convert Line Delimiter To > Unix (LF, \n, 0A, ¶)