remove - ¿Puedo hacer que Git reconozca un archivo UTF-16 como texto?
git tag best practices (6)
¿Has intentado configurar tus .gitattributes
para tratarlo como un archivo de texto?
p.ej:
*.vmc diff
Más detalles en http://www.git-scm.com/docs/gitattributes.html .
Estoy rastreando un archivo de máquina virtual de Virtual PC (* .vmc) en git, y después de hacer un cambio, git identificó el archivo como binario y no lo haría por mí. Descubrí que el archivo estaba codificado en UTF-16.
¿Se puede enseñar a Git reconocer que este archivo es texto y manejarlo apropiadamente?
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 predeterminada en Unices.
Por ejemplo, con los archivos .strings
de Apple solo:
Cree un archivo
.gitattributes
en la raíz de su repositorio con:*.strings diff=localizablestrings
Agregue lo siguiente a su archivo
~/.gitconfig
:[diff "localizablestrings"] textconv = "iconv -f utf-16 -t utf-8"
Fuente: archivos Diff .strings en Git (y publicaciones anteriores desde 2010).
He escrito un pequeño controlador git-diff, to-utf8
, que debería facilitar la diferenciación de cualquier archivo no codificado en ASCII / UTF-8. Puede instalarlo usando las instrucciones aquí: https://github.com/chaitanyagupta/gitutils#to-utf8 (el script to-utf8
está disponible en el mismo repositorio).
Tenga en cuenta que este script requiere que los comandos file
e iconv
estén disponibles en el sistema.
He estado luchando con este problema por un tiempo, y acabo de descubrir (para mí) una solución perfecta:
$ git config --global diff.tool vimdiff # or merge.tool to get merging too!
$ git difftool commit1 commit2
git difftool
toma los mismos argumentos que git diff
would, pero ejecuta un programa de diferencias de su elección en lugar del diff
GNU incorporado. Así que elija un diff multibyte-aware (en mi caso, vim
en modo diff) y simplemente use git difftool
lugar de git diff
.
Encuentra "difftool" demasiado tiempo para escribir? No hay problema:
$ git config --global alias.dt difftool
$ git dt commit1 commit2
Git rocas.
La solución es filtrar a través de cmd.exe /c "type %1"
. El type
interno de cmd hará la conversión, por lo que puede usarlo con la habilidad textconv de git diff para habilitar la diferencia 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 diffs de texto de archivos binarios
Algunas 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 la diferencia del texto que se muestra. Aunque esta conversión pierde cierta 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 usa 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 tiene instalada la herramienta exif), agregue la siguiente sección a su $GIT_DIR/config
(o archivo $HOME/.gitconfig
):
[diff "jpg"]
textconv = exif
Una solución para mingw32 , los fans de cygwin pueden tener que modificar el enfoque. El problema es pasar el nombre del archivo para convertirlo a cmd.exe; usará barras diagonales, y cmd asume separadores del directorio barra invertida.
Paso 1:
Cree el script de un solo argumento que hará la conversión a stdout. c: / path / to / some / script.sh:
#!/bin/bash
SED=''s/////////////g''
FILE=/`echo $1 | sed -e "$SED"/`
cmd.exe /c "type $FILE"
Paso 2:
Configure git para poder usar el archivo de script. Dentro de su configuración de git ( ~/.gitconfig
o .git/config
o vea man git-config
), ponga esto:
[diff "cmdtype"]
textconv = c:/path/to/some/script.sh
Paso 3:
Señale los archivos para aplicar este trabajo a mediante la utilización de archivos .gitattributes (vea man gitattributes (5)):
*vmc diff=cmdtype
luego usa git diff
en tus archivos.
Por defecto, parece que git
no funcionará bien con UTF-16; para dicho archivo, debe asegurarse de que no se realiza ningún procesamiento CRLF
, pero desea que diff
y merge
funcionen como un archivo de texto normal (esto ignora si su terminal / editor puede manejar UTF-16).
Pero mirando la página de .gitattributes
, aquí está el atributo personalizado que es binary
:
[attr]binary -diff -crlf
Por lo tanto, me parece que podría definir un atributo personalizado en su nivel superior .gitattributes
para utf16
(tenga en cuenta que agrego fusión aquí para asegurarse de que se trata como texto):
[attr]utf16 diff merge -crlf
Desde allí, podrá especificar en cualquier archivo .gitattributes
algo así como:
*.vmc utf16
También tenga en cuenta que todavía debe ser capaz de diff
un archivo, incluso si git
piensa que es binario con:
git diff --text
Editar
Esta respuesta básicamente dice que GNU diff wth UTF-16 o incluso UTF-8 no funciona muy bien. Si quieres que git
use una herramienta diferente para ver las diferencias (a través de --ext-diff
), esa respuesta sugiere a Guiffy .
Pero lo que probablemente necesite es simplemente diff
un archivo UTF-16 que contiene solo caracteres ASCII. Una forma de hacer que eso funcione es usar --ext-diff
y el siguiente script de shell:
#!/bin/bash
diff <(iconv -f utf-16 -t utf-8 "$1") <(iconv -f utf-16 -t utf-8 "$2")
Tenga en cuenta que la conversión a UTF-8 también podría funcionar para la fusión, solo tiene que asegurarse de que se realice en ambas direcciones.
En cuanto a la salida al terminal cuando se mira un diff de un archivo UTF-16:
Tratar de diferir de esa manera da como resultado basura binaria arrojada a la pantalla. Si git está usando GNU diff, parecería que GNU diff no es consciente de unicode.
GNU diff realmente no se preocupa por el Unicode, así que cuando usas diff --text solo diffs y saca 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 diferencia que son caracteres ASCII).