Por que o Git trata esse arquivo de texto como um arquivo binário?

150

Eu me pergunto por que o git me diz isso :?

$ git diff MyFile.txt
diff --git a/MyFile.txt b/MyFile.txt
index d41a4f3..15dcfa2 100644
Binary files a/MyFile.txt and b/MyFile.txt differ

Eles não são arquivos de texto?

Eu verifiquei os atributos .gitat e ele está vazio. Por que estou recebendo esta mensagem? Não consigo obter diffs como eu já uso

ADICIONADO:

Eu notei que há @permissões no arquivo, o que é isso? Poderia ser este o motivo?

$ls -all
drwxr-xr-x   5 nacho4d  staff    170 28 Jul 17:07 .
drwxr-xr-x  16 nacho4d  staff    544 28 Jul 16:39 ..
-rw-r--r--@  1 nacho4d  staff   6148 28 Jul 16:15 .DS_Store
-rw-r--r--@  1 nacho4d  staff    746 28 Jul 17:07 MyFile.txt
-rw-r--r--   1 nacho4d  staff  22538  5 Apr 16:18 OtherFile.txt
nacho4d
fonte
4
Pode ser um arquivo codificado em UTF-8.
Marnix van Valen
É suposto ser UTF16 pouco LF endian
nacho4d
1
Na página de lsmanual no Mac OS X: Se o arquivo ou diretório tiver atributos estendidos, o campo de permissões impresso pela -lopção será seguido por um @caractere . Use a opção -@para ver esses atributos estendidos.
ADL
Eu acho que isso pode ser um bug do git. Eu apaguei os atributos estendidos e agora está tudo bem novamente.
Nacho4d 28/07/11
4
@ nacho4d: Isso é estranho, porque o git nem deveria saber que existem atributos estendidos. Se você pudesse reproduzi-lo, valeria a pena aparecer na lista de discussão do git. Como é um bom costume nas vger.kernel.orglistas, você não precisa se inscrever para postar (as pessoas o manterão em CC para obter respostas) e é suposto não dar o volume bastante alto da [email protected]lista.
Jan Hudec

Respostas:

76

Significa simplesmente que, quando o git inspeciona o conteúdo real do arquivo (ele não sabe que uma extensão específica não é um arquivo binário - você pode usar o arquivo de atributos, se desejar explicitamente - consulte as páginas de manual).

Depois de inspecionar o conteúdo do arquivo, ele viu coisas que não estão em caracteres ASCII básicos. Sendo UTF16, espero que ele tenha caracteres "engraçados", por isso acha que é binário.

Existem maneiras de dizer ao git se você possui internacionalização (i18n) ou formatos de caracteres estendidos para o arquivo. Eu não estou suficientemente esclarecido sobre o método exato para definir isso - você pode precisar RT [Full] M ;-)

Edit: uma pesquisa rápida de SO encontrado can-i-make-git-reconhece-um-utf-16-arquivo-como-texto que deve lhe dar algumas pistas.

Philip Oakley
fonte
10
Você está quase mas não completamente errado. O Git inspecionou os arquivos reais e viu personagens 'engraçados' lá. No entanto, ele não "acha" que o UTF-16 é binário. Ele é binário, porque o texto é definido como-ASCII base (que é a única coisa que o built-in diff vai dar resultados úteis para) e UTF-16 não é. Sim, existe uma maneira de dizer ao git para usar diff especial para arquivos definidos por padrão (usando .gitattributes).
Jan Hudec
2
Devo acrescentar que 'personagens engraçados' realmente significa zero bytes.
Jan Hudec
4
Nós dois estamos certos, mas de perspectivas diferentes. Nós dois dizemos "Git inspeciona o conteúdo para determinar seu tipo". Nós ambos dizem que para fazer git sei que deve ser tratado como UTF16 as necessidades do usuário para dizer git via .gitattributesetc.
Philip Oakley
7
@JanHudec: Na sua opinião, TODOS os arquivos são binários.
stolsvik
2
@stolosvik, (and JanH) É um meio-termo mais sutil, pois o UTF-8 inclui os caracteres ASCII de 0 a 127 e todos os outros caracteres Unicode, sem a necessidade de um byte nulo (00h) para qualquer coisa que não seja o nul char (o terminador de string 'C'). Portanto, a definição de texto do Git é que o conteúdo (bem, os primeiros 1k bytes) não deve ter um byte nulo quando codificado em utf-8. Tente stackoverflow.com/questions/2241348/… para uma leitura divertida. Meu comentário original refere-se ao caso em que UTF-16 codificado dados é visto como pares de bytes, então o byte alto para pontos de código ASCII será 00.
Philip Oakley
41

Se você não definiu o tipo de arquivo, o Git tenta determiná-lo automaticamente e um arquivo com linhas realmente longas e talvez alguns caracteres largos (por exemplo, Unicode) sejam tratados como binários. Com o arquivo .gitattributes, você pode definir como o Git interpreta o arquivo. Definir o atributo diff manualmente permite que o Git interprete o conteúdo do arquivo como texto e fará um diff usual.

Apenas adicione um atributo .gitat à sua pasta raiz do repositório e defina o atributo diff nos caminhos ou arquivos. Aqui está um exemplo:

src/Acme/DemoBundle/Resources/public/js/i18n/* diff
doc/Help/NothingToSay.yml                      diff
*.css                                          diff

Se você quiser verificar se há atributos definidos em um arquivo, faça isso com a ajuda do git check-attr

git check-attr --all -- src/my_file.txt

Outra boa referência sobre os atributos do Git pode ser encontrada aqui .

naitsirch
fonte
1
Isso foi útil, mas na verdade está incorreto - o atributo certo diffnão é text. O textatributo não diz ao git para diff usando o texto, mas controla como as terminações de linha são tratadas (normalização para LF). Veja seu link para .gitattributes para mais detalhes.
ErikE
Obrigado @ErikE. Atualizei minha postagem de acordo com o seu comentário e a documentação do Git.
Naitsirch
4
Além disso, você pode definir que tipo de diff deve ser executado. Por exemplo, se é um arquivo xml, você pode usar em diff=xmlvez de apenas diff.
Sandy Chapman
1
Qual é o oposto de check-attr - existe um set-attr? Originalmente, salvei acidentalmente um arquivo como UTF-16, depois o confirmei e o enviei, e agora o BitBucket o vê como UTF-16, mesmo depois de salvá-lo novamente como UTF-8, comprometendo-o e pressionando-o novamente. Isso basicamente torna impossível ler minhas solicitações de recebimento, porque os revisores precisam clicar em cada comentário individual para adicionar comentários.
John Zabroski 4/16/16
21

Eu estava tendo esse problema em que o Git GUI e o SourceTree tratavam os arquivos Java / JS como binários e, portanto, não via diferença.

A criação do arquivo chamado "atributos" na pasta .git \ info com o seguinte conteúdo resolveu o problema

*.java diff
*.js diff
*.pl diff
*.txt diff
*.ts diff
*.html diff

Se você quiser fazer essa alteração em todos os repositórios, poderá adicionar o arquivo de atributos no seguinte local $ HOME / .config / git / attribute

Hemant
fonte
1
Observe também o <project-root>/.gitattributesarquivo, que ativa a alteração para todos os colaboradores e apenas para o projeto relevante.
jpaugh
A adição * difffoi útil para mim: mostra a diferença em todos os tipos de arquivos. Mas sua solução é melhor, por evitar mostrar diferenças desnecessárias em arquivos binários grandes.
Boolean_Type
sim! Isso ajuda!
WildCat
19

O Git até determinará que é binário se você tiver uma linha super longa no seu arquivo de texto. Eu quebrei uma String longa, transformando-a em várias linhas de código-fonte e, de repente, o arquivo passou de 'binário' para um arquivo de texto que eu pude ver (no SmartGit).

Portanto, não continue digitando muito à direita sem pressionar 'Enter' no seu editor - caso contrário, mais tarde, o Git pensará que você criou um arquivo binário.

Chris Murphy
fonte
1
Esta é uma informação correta. Eu estava tentando controlar diffs em um MySQL Dump extremamente grande (arquivo .sql), mas o git o trata como um arquivo binário, mesmo que tenha apenas dados ASCII / UTF8. O motivo é que as linhas são super longas (insere valores (um), (dois), (três), (...), (3 milhões ...); Estranhamente, para cada commit, o repositório git não aumentar em 1.7GB, mas apenas ~ 350MB Talvez, git é comprimir o arquivo "binário" antes de o guardar..
Alexandre T.
@AlexandreT. De fato, o Git compacta os blobs de arquivo (usando GZip, IIRC).
jpaugh
11

Eu tive esse mesmo problema depois de editar um dos meus arquivos em um novo editor. Acontece que o novo editor usou uma codificação diferente (Unicode) do que o meu editor antigo (UTF-8). Então, eu simplesmente disse ao meu novo editor para salvar meus arquivos com UTF-8 e, em seguida, o git mostrou minhas alterações corretamente novamente e não o vi como um arquivo binário.

Eu acho que o problema era simplesmente que o git não sabe como comparar arquivos de diferentes tipos de codificação. Portanto, o tipo de codificação que você usa realmente não importa, desde que permaneça consistente.

Não testei, mas tenho certeza de que, se eu tivesse confirmado meu arquivo com a nova codificação Unicode, na próxima vez em que fizesse alterações, ele mostraria as alterações corretamente e não a detectaria como binária, pois estaria comparando dois arquivos codificados em Unicode, e não um arquivo UTF-8 com um arquivo Unicode.

Você pode usar um aplicativo como o Notepad ++ para ver e alterar facilmente o tipo de codificação de um arquivo de texto; Abra o arquivo no Notepad ++ e use o menu Codificação na barra de ferramentas.

cão mortal
fonte
1
Unicode não é uma codificação. É um conjunto de caracteres e UTF-8 é um da sua codificação, ou seja, a maneira de codificar um ponto de código Unicode
phuclv
1
Isso não resolve o problema, apenas o evita. O problema é que o git ou sua ferramenta diff não reconhece adequadamente os arquivos de texto ou não permite que o usuário substitua facilmente seu comportamento.
Preza8 29/07/19
6

Eu tive o mesmo problema. Encontrei o tópico ao pesquisar a solução no google, ainda não encontrei nenhuma pista. Mas acho que encontrei o motivo depois de estudar, o exemplo abaixo explicará claramente minha pista.

    echo "new text" > new.txt
    git add new.txt
    git commit -m "dummy"

por enquanto, o arquivo new.txt é considerado como um arquivo de texto.

    echo -e "newer text\000" > new.txt
    git diff

você obterá esse resultado

diff --git a/new.txt b/new.txt
index fa49b07..410428c 100644
Binary files a/new.txt and b/new.txt differ

e tente isso

git diff -a

você vai ficar abaixo

    diff --git a/new.txt b/new.txt
    index fa49b07..9664e3f 100644
    --- a/new.txt
    +++ b/new.txt
    @@ -1 +1 @@
    -new file
    +newer text^@
Howard
fonte
5

Tivemos um caso em que um arquivo .html era visto como binário sempre que tentávamos fazer alterações. Muito uncool para não ver diffs. Para ser sincero, não verifiquei todas as soluções aqui, mas o que funcionou para nós foi o seguinte:

  1. O arquivo foi removido (na verdade, foi movido para minha área de trabalho) e confirmado o arquivo git deletion. Git dizDeleted file with mode 100644 (Regular) Binary file differs
  2. Adicionar novamente o arquivo (na verdade, ele foi movido da minha área de trabalho para o projeto). Git diz que New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsagora o arquivo foi adicionado como um arquivo de texto comum

A partir de agora, qualquer alteração feita no arquivo será vista como uma comparação de texto regular. Você também pode esmagar esses commits (1, 2 e 3 sendo a alteração real que você faz), mas eu prefiro poder ver no futuro o que fiz. O esmagamento 1 e 2 mostrará uma alteração binária.

StuFF mc
fonte
Semelhante com um ou dois arquivos cpp (compilados com sucesso) enviados do VS. Renderiza o gui do Github para Compare ridículo. Um não gostaria de ser uma mosca no sino em um intercâmbio tão ding dong, - VS de um lado dizendo que é Github, e do outro lado o Github dizendo que é VS. :(
Laurie Stearn 28/01
4

Por essa resposta útil , você pode perguntar diretamente ao Git por que ele trata um arquivo de uma maneira específica:

cd directory/of/interest
file *

Produz resultados úteis como este:

$ file *
CR6Series_stats resaved.dat: ASCII text, with very long lines, with CRLF line terminators
CR6Series_stats utf8.dat:    UTF-8 Unicode (with BOM) text, with very long lines, with CRLF line terminators
CR6Series_stats.dat:         ASCII text, with very long lines, with CRLF line terminators
readme.md:                   ASCII text, with CRLF line terminators
patricktokeeffe
fonte
6
filenão é um comando git. É uma ferramenta totalmente separada, empacotada com o git no Windows. Existe documentação mostrando que é isso que o git usa para detecção de arquivos binários?
Max
4

Isso também é causado (pelo menos no Windows) por arquivos de texto que possuem UTF-8 com codificação de BOM . Alterar a codificação para UTF-8 normal imediatamente fez o Git ver o arquivo como type = text

Robba
fonte
1

Eu tive uma instância em que .gitignorecontinha uma \rsequência dupla (retorno de carro) por objetivo.

Esse arquivo foi identificado como binário pelo git. Adicionando um .gitattributesarquivo ajudou.

# .gitattributes file
.gitignore diff
Erik Zivkovic
fonte
1
Trabalhou. Eu também tive um duplo \ r para ignorar alguns arquivos do sistema "Icon \ r \ r". É bom conhecer a causa e a correção.
hsandt
1

Se git check-attr --all -- src/my_file.txtindica que seu arquivo está sinalizado como binário e você não o definiu como binário .gitattributes, verifique-o /.git/info/attributes.

Coberlin
fonte
0

Mude o Aux.js para outro nome, como Sig.js.

A árvore de origem ainda a mostra como um arquivo binário, mas você pode prepará-lo (adicioná-lo) e confirmar.

Oscar Zhou1989
fonte
0

Eu tive um problema semelhante ao colar algum texto de uma mensagem binária do Kafka, que inseria caracteres não visíveis e fazia com que o git pensasse que o arquivo era binário.

Encontrei os caracteres incorretos pesquisando o arquivo usando regex [^ -~\n\r\t]+.

  • [ coincidir com caracteres neste conjunto
  • ^ corresponde a caracteres que não estão neste conjunto
  • -~ corresponde a todos os caracteres de '' (espaço) a '~'
  • \n nova linha
  • \r retorno de carro
  • \t aba
  • ] fechar conjunto
  • + corresponde a um ou mais desses caracteres
Martyn Davis
fonte
-2

Passei várias horas examinando tudo nesta lista tentando descobrir por que um dos projetos de teste em minha solução não estava adicionando nenhum teste ao explorador.

No meu caso, aconteceu que, de alguma forma (provavelmente devido a uma má fusão do git em algum lugar), o VS havia perdido completamente uma referência ao projeto. Ainda estava em construção, mas notei que apenas construía as dependências.

Percebi então que ele não estava aparecendo na lista de dependências, então removi e adicionei novamente o projeto de teste e todos os meus testes finalmente apareceram.

cirro
fonte
2
O Visual Studio realmente não é relevante aqui.
jpaugh