Estoy rastreando un archivo de máquina virtual de PC virtual (* .vmc) en git, y después de hacer un cambio, git identificó el archivo como binario y no me diferenció. Descubrí que el archivo estaba codificado en UTF-16.
¿Se puede enseñar a git a reconocer que este archivo es texto y manejarlo adecuadamente?
Estoy usando git en Cygwin, con core.autocrlf establecido en falso. Podría usar mSysGit o git en UNIX, si es necesario.

Hay una solución muy simple que funciona de forma inmediata en Unices.
Por ejemplo, con los
.stringsarchivos de Apple solo:Cree un
.gitattributesarchivo en la raíz de su repositorio con:Agregue lo siguiente a su
~/.gitconfigarchivo:Fuente: archivos Diff .strings en Git (y una publicación anterior de 2010).
fuente
iconves "otra herramienta" de la misma manera que lo es Vim o Beyond Compare (no es parte del paquete git).vimdiffyiconvambos ya están presentes en macOS, por lo que no necesita molestarse en preguntarse dónde conseguirlos, y hacen el trabajo¿Has intentado configurar tu
.gitattributespara tratarlo como un archivo de texto?p.ej:
Más detalles en http://www.git-scm.com/docs/gitattributes.html .
fuente
setydiff...*.vmc diff,*.sql diffetc. se necesita para establecer el atributo 'diff' para la ruta especificada. (No puedo editar la respuesta). Sin embargo, hay dos advertencias: las diferencias se muestran con un espacio entre cada personaje y no es posible "poner en escena" o "descartar trozo" para esos archivos problemáticos.Por defecto, parece
gitque no funcionará bien con UTF-16; para dicho archivo, debe asegurarse de que noCRLFse realice ningún procesamiento en él, pero deseadiffymergetrabajar como un archivo de texto normal (esto ignora si su terminal / editor puede manejar UTF-16 o no).Pero mirando la página de
.gitattributesmanual , aquí está el atributo personalizado que esbinary:Entonces, me parece que podría definir un atributo personalizado en su nivel superior
.gitattributesparautf16(tenga en cuenta que agrego fusionar aquí para asegurarme de que se trate como texto):Desde allí, podría especificar en cualquier
.gitattributesarchivo algo como:También tenga en cuenta que aún debe poder crear
diffun archivo, incluso sigitcree que es binario con:Editar
Esta respuesta básicamente dice que la diferencia de GNU con UTF-16 o incluso UTF-8 no funciona muy bien. Si desea
gitutilizar una herramienta diferente para ver las diferencias (vía--ext-diff), esa respuesta sugiere Guiffy .Pero lo que probablemente necesite es solo
diffun archivo UTF-16 que contenga solo caracteres ASCII. Una forma de hacer que eso funcione es usar--ext-diffel siguiente script de shell:Tenga en cuenta que la conversión a UTF-8 también podría funcionar para la fusión, solo debe asegurarse de que se realice en ambas direcciones.
En cuanto a la salida al terminal cuando se mira una diferencia de un archivo UTF-16:
GNU diff realmente no se preocupa por unicode, por lo que cuando usa diff --text solo difiere y genera el texto. El problema es que el terminal que está utilizando no puede manejar el UTF-16 que se emite (combinado con las marcas de diferencias que son caracteres ASCII).
fuente
La solución es filtrar a través
cmd.exe /c "type %1". cmd'stypebuiltin realizará la conversión, por lo que puede usar eso con la capacidad textconv de git diff para habilitar la diferenciación de texto de los archivos UTF-16 (también debería funcionar con UTF-8, aunque no probado).Citando de la página del manual de gitattributes:
Realizar diferencias de texto de archivos binarios
A veces es deseable ver la diferencia de una versión convertida por texto de algunos archivos binarios. Por ejemplo, un documento de procesador de textos se puede convertir a una representación de texto ASCII y mostrar la diferencia del texto. Aunque esta conversión pierde algo de información, la diferencia resultante es útil para la visualización humana (pero no se puede aplicar directamente).
La opción de configuración textconv se utiliza para definir un programa para realizar dicha conversión. El programa debe tomar un solo argumento, el nombre de un archivo para convertir, y producir el texto resultante en stdout.
Por ejemplo, para mostrar la diferencia de la información exif de un archivo en lugar de la información binaria (suponiendo que tenga instalada la herramienta exif), agregue la siguiente sección a su
$GIT_DIR/configarchivo (o$HOME/.gitconfigarchivo):Una solución para mingw32 , los fanáticos de pueden tener que alterar el enfoque. El problema es pasar el nombre del archivo para convertirlo a cmd.exe: utilizará barras diagonales y cmd asume separadores de directorio de barra invertida.
Paso 1:
Cree el script de argumento único que realizará la conversión a stdout. c: \ ruta \ a \ algunos \ script.sh:
Paso 2:
Configure git para poder usar el archivo de script. Dentro de su git config (
~/.gitconfigo.git/configni verman git-config), poner esto:Paso 3:
Señale los archivos a los que se debe aplicar este trabajo utilizando archivos .gitattributes (consulte man gitattributes (5)):
luego úselo
git diffen sus archivos.fuente
cmd //c type "${1//\//\\}".textconv = powershell -NoProfile -Command \"& {Get-Content \\$args[0]}\"git recientemente ha comenzado a comprender codificaciones como utf16. Ver gitattributes docs, buscar
working-tree-encoding[¡Asegúrese de que su página de manual coincida ya que esto es bastante nuevo!]
Si (por ejemplo) el archivo es UTF-16 sin BOM en la máquina Windows, agréguelo a su
.gitattributesarchivoSi UTF-16 (con bom) en * nix, hágalo:
(Reemplazar
*.vmccon*.whateverparawhateverlos ficheros del tipo que necesita para manejar)Consulte: Soporte de codificación de árbol de trabajo "UTF-16LE-BOM" .
Agregado luego
Después de @Hackslash, uno puede encontrar que esto es insuficiente
Para obtener buenas diferencias de texto necesitas
Poniendo ambas obras también
Pero es discutible
eol=...implicatextEl problema
Git tiene un macro-atributo
binaryque significa-text -diff. Lo contrario+text +diffno está disponible incorporado, pero git proporciona las herramientas (¡creo!) Para sintetizarloLa solución
Git le permite a uno definir nuevos atributos de macro.
Propondría que la parte superior de la
.gitattributesarchivo que tienesLuego, para todas las rutas que deben ser text y diff do
Tenga en cuenta que en la mayoría de los casos nos gustaría la codificación predeterminada (utf-8) y la eol predeterminada (nativa) y así lo se pueden eliminar.
La mayoría de las líneas deberían verse como
¿Por qué no solo usar diff?
Práctico: en la mayoría de los casos queremos eol nativo. Lo que significa que no
eol=.... Portextlo tanto , no se implicará y debe expresarse explícitamente.Conceptual: el texto V binario es la distinción fundamental. eol, codificación, diff, etc. son solo algunos aspectos.
Descargo de responsabilidad
Debido a los tiempos extraños en que vivimos, no tengo una máquina con un git de trabajo actual. Por lo tanto, en este momento no puedo verificar la última incorporación. Si alguien encuentra algo mal, lo enmendaré / eliminaré.
fuente
*.vmc diff working-tree-encoding=UTF-16LE-BOM eol=CRLFtextsolo que no obtuviste buenas diferencias de texto? ¿Puedes comprobar eso con ambostextydifftodo funciona bien? En cuyo caso haré una recomendación diferentetextsolo da como resultado una comparación binaria. Puedo hacerdiffotext diffy funciona. Necesitaba agregar-BOMsimplemente porque mi archivo tenía una lista de materiales, YMMV.He escrito un pequeño controlador git-diff
to-utf8, que debería facilitar la difusión de cualquier archivo codificado que no sea ASCII / UTF-8. Puede instalarlo siguiendo las instrucciones aquí: https://github.com/chaitanyagupta/gitutils#to-utf8 (elto-utf8script está disponible en el mismo repositorio).Tenga en cuenta que este script requiere que tanto los comandos
filecomo losiconvcomandos estén disponibles en el sistema.fuente
Tenido este problema en Windows recientemente, y las
dos2unixyunix2doslos contenedores que se suministran con git para ventanas resolvieron el problema. Por defecto están ubicados enC:\Program Files\Git\usr\bin\. Observe que esto solo funcionará si su archivo no necesita ser UTF-16. Por ejemplo, alguien codificó accidentalmente un archivo de Python como UTF-16 cuando no era necesario (en mi caso).y
fuente