¿Por qué Git trata este archivo de texto como un archivo binario?

150

Me pregunto por qué git me dice esto :?

$ 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

¿No son archivos de texto?

He comprobado los atributos .gitattributes y está vacío. ¿Por qué recibo este mensaje? Ya no puedo obtener diferencias como solía hacerlo

ADICIONAL:

He notado que hay un @en los permisos de archivo, ¿qué es esto? Podría ser ésta la razón?

$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
fuente
44
Podría ser un archivo codificado UTF-8.
Marnix van Valen
Se supone que es UTF16 little endian LF
nacho4d
1
Desde la página de lsmanual en Mac OS X: si el archivo o directorio tiene atributos extendidos, el campo de permisos impreso por la -lopción va seguido de un @carácter . Use la opción -@para ver estos atributos extendidos.
adl
Creo que esto podría ser un error de git. Eliminé los atributos extendidos y ahora todo vuelve a estar bien.
nacho4d
44
@ nacho4d: Eso es extraño, porque git ni siquiera debería saber que hay atributos extendidos. Si pudiera reproducirlo, valdría la pena que aparezca en la lista de correo de git. Como es una buena costumbre en las vger.kernel.orglistas, no tiene que suscribirse para publicar (las personas lo mantendrán en contacto con CC) para obtener respuestas) y se supone que no deben dar el volumen bastante alto de la [email protected]lista.
Jan Hudec

Respuestas:

76

Simplemente significa que cuando git inspecciona el contenido real del archivo (no sabe que ninguna extensión dada no es un archivo binario; puede usar el archivo de atributos si desea decirlo explícitamente; vea las páginas del manual).

Después de inspeccionar el contenido del archivo, ha visto cosas que no están en caracteres ascii básicos. Siendo UTF16, espero que tenga caracteres 'divertidos', por lo que cree que es binario.

Hay formas de decirle a git si tiene internacionalización (i18n) o formatos de caracteres extendidos para el archivo. No estoy suficientemente informado sobre el método exacto para configurar eso: es posible que necesite RT [Completo] M ;-)

Editar: una búsqueda rápida de SO encontró can-i-make-git-Recognize-a-utf-16-file-as-text que debería darle algunas pistas.

Philip Oakley
fuente
10
Casi no estás completamente equivocado. Git inspeccionó los archivos reales y vio personajes 'divertidos' allí. Sin embargo, no "piensa" que UTF-16 sea binario. Que es binario, ya que el texto se define como basado en ASCII (que es lo único que el incorporado en dif dará resultados utilizables para) y UTF-16 no lo es. Sí, hay una manera de decirle a git que use diff especial para archivos definidos por patrón (usando .gitattributes).
Jan Hudec
2
Debo agregar que "caracteres divertidos" realmente significa cero bytes.
Jan Hudec
44
Ambos tenemos razón, pero desde diferentes perspectivas. Ambos decimos "Git inspecciona el contenido para determinar su tipo". Ambos decimos que para que git sepa que debe tratarse como UTF16, el usuario debe decirle a git a través de .gitattributesetc.
Philip Oakley
77
@ JanHudec: En su opinión, TODOS los archivos son binarios.
stolsvik
2
@stolosvik, (y JanH) Es un término medio más sutil en el sentido de que UTF-8 incluye tanto los caracteres ASCII de base 0-127 como todos los demás caracteres Unicode, sin necesidad de un byte nulo (00h) para cualquier otra cosa que no sea el nul char (el terminador de cadena 'C'). Por lo tanto, la definición de texto de Git es que el contenido (bueno, los primeros 1k bytes) no debe tener un byte nulo cuando se codifica utf-8. Prueba stackoverflow.com/questions/2241348/… para una lectura divertida. Mi comentario original se refiere al caso en que los datos codificados en UTF-16 se ven como pares de bytes, por lo que el byte alto para los puntos de código ASCII será 00.
Philip Oakley
41

Si no ha establecido el tipo de archivo, Git intenta determinarlo automáticamente y un archivo con líneas realmente largas y quizás algunos caracteres anchos (por ejemplo, Unicode) se trata como binario. Con el archivo .gitattributes puede definir cómo Git interpreta el archivo. Establecer la diferencia atributo manualmente le permite a Git interpretar el contenido del archivo como texto y hará un diff habitual.

Simplemente agregue un atributo .gitattributes a su carpeta raíz del repositorio y establezca el atributo diff en las rutas o archivos. Aquí hay un ejemplo:

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

Si desea verificar si hay atributos establecidos en un archivo, puede hacerlo con la ayuda de git check-attr

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

Otra buena referencia sobre los atributos de Git se puede encontrar aquí .

naitsirch
fuente
1
Esto fue útil, pero en realidad es incorrecto; el atributo correcto es diff, no text. El textatributo no le dice a git que difiera usando texto, sino que controla cómo se manejan las terminaciones de línea (normalización a LF). Vea su enlace a .gitattributes para más detalles.
ErikE
Gracias @ErikE. He actualizado mi publicación de acuerdo con su comentario y la documentación de Git.
naitsirch
44
Además, puede establecer qué tipo de diff se debe realizar. Por ejemplo, si es un archivo xml que puede usar en diff=xmllugar de solo diff.
Sandy Chapman
1
¿Qué es lo contrario de check-attr? ¿Hay un set-attr? Originalmente, accidentalmente guardé un archivo como UTF-16, luego lo comprometí y lo empujé, y ahora BitBucket lo ve como UTF-16, incluso después de volver a guardarlo como UTF-8, comprometiéndolo y presionándolo nuevamente. Básicamente, esto hace que mis solicitudes de extracción sean imposibles de leer porque los revisores deben hacer clic en cada comentario individual para agregar comentarios de revisión.
John Zabroski el
21

Estaba teniendo este problema donde Git GUI y SourceTree trataban los archivos Java / JS como binarios y, por lo tanto, no podían ver la diferencia

Crear un archivo llamado "atributos" en la carpeta .git \ info con el siguiente contenido resolvió el problema

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

Si desea realizar este cambio para todos los repositorios, puede agregar el archivo de atributos en la siguiente ubicación $ HOME / .config / git / atributos

Hemant
fuente
1
También tenga en cuenta el <project-root>/.gitattributesarchivo, que activa el cambio para todos los contribuyentes, y solo para el proyecto relevante.
jpaugh
Agregar * difffue útil para mí: muestra la diferencia en todos los tipos de archivos. Pero su solución es mejor, porque evita mostrar las diferencias innecesarias en archivos binarios grandes.
Boolean_Type
¡Si! ¡Esto ayuda!
WildCat
19

Git incluso determinará que es binario si tiene una línea súper larga en su archivo de texto. Rompí una cadena larga, convirtiéndola en varias líneas de código fuente, y de repente el archivo pasó de ser 'binario' a un archivo de texto que pude ver (en SmartGit).

Por lo tanto, no siga escribiendo demasiado a la derecha sin presionar 'Enter' en su editor; de lo contrario, Git pensará que ha creado un archivo binario.

Chris Murphy
fuente
1
Esta es una información correcta. Estaba tratando de controlar las diferencias con un volcado MySQL extremadamente grande (archivo .sql), pero git lo trata como un archivo binario, incluso si solo tiene datos ASCII / UTF8. La razón es que las líneas son muy largas (inserte valores (uno), (dos), (tres), (...), (3 millones ...); Extrañamente, para cada confirmación, el repositorio git hace no aumenta en 1.7gb, pero solo ~ 350mb. Quizás, git está comprimiendo el archivo "binario" antes de guardarlo.
Alexandre T.
@AlexandreT. De hecho, Git comprime blobs de archivos (usando GZip, IIRC).
jpaugh
11

Tuve el mismo problema después de editar uno de mis archivos en un nuevo editor. Resulta que el nuevo editor utilizó una codificación diferente (Unicode) que mi antiguo editor (UTF-8). Así que simplemente le dije a mi nuevo editor que guardara mis archivos con UTF-8 y luego git mostró mis cambios nuevamente y no lo vi como un archivo binario.

Creo que el problema era simplemente que git no sabe cómo comparar archivos de diferentes tipos de codificación. Por lo tanto, el tipo de codificación que usa realmente no importa, siempre que permanezca consistente.

No lo probé, pero estoy seguro de que si hubiera confirmado mi archivo con la nueva codificación Unicode, la próxima vez que realice cambios en ese archivo habría mostrado los cambios correctamente y no lo habría detectado como binario, ya que entonces habría estado comparando dos archivos codificados Unicode, y no un archivo UTF-8 con un archivo Unicode.

Puede usar una aplicación como Notepad ++ para ver y cambiar fácilmente el tipo de codificación de un archivo de texto; Abra el archivo en Notepad ++ y use el menú Codificación en la barra de herramientas.

perro mortal
fuente
1
Unicode no es una codificación. Es un juego de caracteres y UTF-8 es una de sus codificaciones, es decir, la forma de codificar un punto de código Unicode
phuclv
1
Esto no resuelve el problema, solo lo evita. El problema es que git o su herramienta diff no reconoce correctamente los archivos de texto o no permite fácilmente que el usuario anule su comportamiento.
Preza8
6

He tenido el mismo problema Encontré el hilo cuando busco solución en google, aún no encuentro ninguna pista. Pero creo que encontré la razón después de estudiar, el siguiente ejemplo explicará claramente mi pista.

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

por ahora, el archivo new.txt se considera como un archivo de texto.

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

obtendrás este resultado

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

y prueba esto

git diff -a

llegarás abajo

    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
fuente
5

Tuvimos este caso en el que un archivo .html se veía como binario cada vez que intentábamos hacer cambios en él. Muy frío para no ver diferencias. Para ser honesto, no verifiqué todas las soluciones aquí, pero lo que funcionó para nosotros fue lo siguiente:

  1. Eliminó el archivo (en realidad lo movió a mi escritorio) y confirmó el git deletion . Git diceDeleted file with mode 100644 (Regular) Binary file differs
  2. Vuelva a agregar el archivo (en realidad lo movió de mi escritorio al proyecto). Git dice que New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsel archivo ahora se agrega como un archivo de texto normal

De ahora en adelante, cualquier cambio que hice en el archivo se ve como una diferencia de texto normal. También podría aplastar estas confirmaciones (1, 2 y 3 son el cambio real que realiza), pero prefiero poder ver en el futuro lo que hice. El aplastamiento 1 y 2 mostrará un cambio binario.

Stuff mc
fuente
Similar con uno o dos archivos cpp (compilados con éxito) empujados desde VS. Representa la interfaz gráfica de usuario de Github para Comparar ridículo. Uno no desearía ser una mosca en la campana en un intercambio de ding dong, - VS de un lado diciendo que es Github, y del otro lado Github diciendo que es VS. :(
Laurie Stearn
4

Según esta útil respuesta , puede preguntarle directamente a Git por qué trata un archivo de una manera particular:

cd directory/of/interest
file *

Produce resultados útiles 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
fuente
66
fileNo es un comando git. Es una herramienta totalmente separada empaquetada con git en Windows. ¿Existe documentación que muestre que esto es lo que usa git para la detección de archivos binarios?
Max
4

Esto también es causado (al menos en Windows) por archivos de texto que tienen UTF-8 con codificación BOM . Cambiar la codificación a UTF-8 normal hizo que Git viera el archivo como tipo = texto

Robba
fuente
1

Tuve una instancia donde .gitignorecontenía una \rsecuencia doble (retorno de carro) por propósito.

Ese archivo fue identificado como binario por git. Agregar un .gitattributesarchivo ayudó.

# .gitattributes file
.gitignore diff
Erik Zivkovic
fuente
1
Trabajó. También tuve un doble \ r para ignorar algunos archivos "Icon \ r \ r" del sistema operativo. Es bueno saber la causa y la solución.
hsandt
1

Si git check-attr --all -- src/my_file.txtindica que su archivo está marcado como binario y no lo ha configurado como binario .gitattributes, verifíquelo /.git/info/attributes.

coberlin
fuente
0

Cambie Aux.js a otro nombre, como Sig.js.

El árbol fuente todavía lo muestra como un archivo binario, pero puede organizarlo (agregarlo) y confirmar.

Oscar Zhou1989
fuente
0

Tuve un problema similar al pegar un texto de un mensaje binario de Kafka, que insertó caracteres no visibles y causó que git pensara que el archivo es binario.

Encontré los caracteres ofensivos buscando en el archivo usando expresiones regulares [^ -~\n\r\t]+.

  • [ emparejar personajes en este conjunto
  • ^ coincide con los personajes que no están en este conjunto
  • -~ coincide con todos los caracteres desde '' (espacio) hasta '~'
  • \n nueva línea
  • \r retorno de carro
  • \t lengüeta
  • ] conjunto cerrado
  • + coincidir con uno o más de estos personajes
Martyn Davis
fuente
-2

Acabo de pasar varias horas revisando todo en esta lista tratando de averiguar por qué uno de los proyectos de prueba en mi solución no agregaba ninguna prueba al explorador.

Resultó en mi caso que de alguna manera (probablemente debido a una fusión pobre de git en alguna parte) que VS había perdido por completo una referencia al proyecto. Todavía estaba en construcción, pero noté que solo construía las dependencias.

Luego noté que no se mostraba en la lista de dependencias en sí, así que eliminé y volví a agregar el proyecto de prueba y todas mis pruebas aparecieron finalmente.

cirro
fuente
2
Visual Studio realmente no es relevante aquí.
jpaugh