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
.strings
archivos de Apple solo:Cree un
.gitattributes
archivo en la raíz de su repositorio con:Agregue lo siguiente a su
~/.gitconfig
archivo:Fuente: archivos Diff .strings en Git (y una publicación anterior de 2010).
fuente
iconv
es "otra herramienta" de la misma manera que lo es Vim o Beyond Compare (no es parte del paquete git).vimdiff
yiconv
ambos 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
.gitattributes
para tratarlo como un archivo de texto?p.ej:
Más detalles en http://www.git-scm.com/docs/gitattributes.html .
fuente
set
ydiff
...*.vmc diff
,*.sql diff
etc. 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
git
que no funcionará bien con UTF-16; para dicho archivo, debe asegurarse de que noCRLF
se realice ningún procesamiento en él, pero deseadiff
ymerge
trabajar como un archivo de texto normal (esto ignora si su terminal / editor puede manejar UTF-16 o no).Pero mirando la página de
.gitattributes
manual , aquí está el atributo personalizado que esbinary
:Entonces, me parece que podría definir un atributo personalizado en su nivel superior
.gitattributes
parautf16
(tenga en cuenta que agrego fusionar aquí para asegurarme de que se trate como texto):Desde allí, podría especificar en cualquier
.gitattributes
archivo algo como:También tenga en cuenta que aún debe poder crear
diff
un archivo, incluso sigit
cree 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
git
utilizar una herramienta diferente para ver las diferencias (vía--ext-diff
), esa respuesta sugiere Guiffy .Pero lo que probablemente necesite es solo
diff
un archivo UTF-16 que contenga solo caracteres ASCII. Una forma de hacer que eso funcione es usar--ext-diff
el 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'stype
builtin 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/config
archivo (o$HOME/.gitconfig
archivo):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 (
~/.gitconfig
o.git/config
ni 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 diff
en 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
.gitattributes
archivoSi UTF-16 (con bom) en * nix, hágalo:
(Reemplazar
*.vmc
con*.whatever
parawhatever
los 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=...
implicatext
El problema
Git tiene un macro-atributo
binary
que significa-text -diff
. Lo contrario+text +diff
no 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
.gitattributes
archivo 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=...
. Portext
lo 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=CRLF
text
solo que no obtuviste buenas diferencias de texto? ¿Puedes comprobar eso con ambostext
ydiff
todo funciona bien? En cuyo caso haré una recomendación diferentetext
solo da como resultado una comparación binaria. Puedo hacerdiff
otext diff
y funciona. Necesitaba agregar-BOM
simplemente 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-utf8
script está disponible en el mismo repositorio).Tenga en cuenta que este script requiere que tanto los comandos
file
como losiconv
comandos estén disponibles en el sistema.fuente
Tenido este problema en Windows recientemente, y las
dos2unix
yunix2dos
los 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