Могу ли я заставить git распознавать файл UTF-16 как текст?

Я отслеживаю файл виртуальной машины Virtual PC (*.vmc) в git, и после внесения изменений git идентифицировал файл как двоичный и не стал его разглядывать. Я обнаружил, что файл был закодирован в UTF-16.

Можно ли научить git распознавать этот файл как текст и обрабатывать его соответствующим образом?

Я использую git под Cygwin, для core.autocrlf установлено значение false. Я мог бы использовать mSysGit или git под UNIX, если это необходимо.

10 ответов

Решение

Некоторое время я боролся с этой проблемой и только что нашел (для меня) идеальное решение:

$ git config --global diff.tool vimdiff      # or merge.tool to get merging too!
$ git difftool commit1 commit2

git difftool принимает те же аргументы, что и git diff будет, но запускает программу сравнения по вашему выбору вместо встроенного GNU diff, Так что выберите многобайтовый diff (в моем случае, vim в режиме сравнения) и просто использовать git difftool вместо git diff,

Найти "difftool" слишком долго, чтобы напечатать? Нет проблем:

$ git config --global alias.dt difftool
$ git dt commit1 commit2

Мерзкие камни.

Существует очень простое решение, которое работает из коробки на Unices.

Например, с Apple .strings файлы просто:

  1. Создать .gitattributes файл в корне вашего хранилища с:

    *.strings diff=localizablestrings
    
  2. Добавьте следующее к вашему ~/.gitconfig файл:

    [diff "localizablestrings"]
    textconv = "iconv -f utf-16 -t utf-8"
    

Источник: Diff.strings файлы в Gitболее ранняя запись от 2010 года).

Вы пытались настроить свой .gitattributes рассматривать это как текстовый файл?

например:

*.vmc diff

Более подробная информация на http://www.git-scm.com/docs/gitattributes.html.

По умолчанию это выглядит так git не будет хорошо работать с UTF-16; для такого файла вы должны убедиться, что нет CRLF обработка сделана на нем, но вы хотите diff а также merge работать как обычный текстовый файл (это игнорирует, может ли ваш терминал / редактор обрабатывать UTF-16).

Но, глядя на .gitattributes manpage, вот пользовательский атрибут, который binary:

[attr]binary -diff -crlf

Так что мне кажется, что вы можете определить пользовательский атрибут на вашем верхнем уровне .gitattributes за utf16 (обратите внимание, что я добавляю сюда слияние, чтобы быть уверенным, что он рассматривается как текст):

[attr]utf16 diff merge -crlf

Оттуда вы сможете указать в любом .gitattributes подать что-то вроде:

*.vmc utf16

Также обратите внимание, что вы все еще должны быть в состоянии diff файл, даже если git думает, что это двоичный файл с:

git diff --text

редактировать

Этот ответ в основном говорит о том, что GNU diff с UTF-16 или даже UTF-8 работает не очень хорошо. Если вы хотите иметь git использовать другой инструмент, чтобы увидеть различия (через --ext-diff), этот ответ предполагает Guiffy.

Но то, что вам, вероятно, нужно, это просто diff файл UTF-16, который содержит только символы ASCII. Способ заставить это работать - использовать --ext-diff и следующий сценарий оболочки:

#!/bin/bash
diff <(iconv -f utf-16 -t utf-8 "$1") <(iconv -f utf-16 -t utf-8 "$2")

Обратите внимание, что преобразование в UTF-8 может также работать для слияния, вам просто нужно убедиться, что это сделано в обоих направлениях.

Что касается вывода на терминал при просмотре различий файла UTF-16:

Попытка различий таким образом приводит к бинарному мусору, выбрасываемому на экран. Если git использует GNU diff, может показаться, что GNU diff не поддерживает Unicode.

GNU diff на самом деле не заботится о юникоде, поэтому, когда вы используете diff --text, он просто переводит и выводит текст. Проблема в том, что используемый вами терминал не может обрабатывать испускаемый UTF-16 (в сочетании с метками diff, которые являются символами ASCII).

Git недавно начал понимать такие кодировки, как utf16. Смотрите документы gitattributes, ищите working-tree-encoding

[Убедитесь, что ваша страница справочника соответствует, так как это совершенно новый!]

Если (скажем) файл на компьютере с операционной системой Windows - utf-16 без bom, добавьте его в файл gitattributes

*.vmc text working-tree-encoding=UTF-16LE eol=CRLF

Если utf-16 (с бомбой) на *nix, сделайте это

*.vmc text working-tree-encoding=UTF-16 eol=LF

Решение состоит в том, чтобы отфильтровать cmd.exe /c "type %1", CMD-х type Встроенный будет выполнять преобразование, и вы можете использовать это с возможностью textconv git diff, чтобы включить различие текста файлов UTF-16 (должно работать и с UTF-8, хотя и не проверялось).

Цитирование из справочной страницы gitattributes:


Выполнение текстовых различий бинарных файлов

Иногда желательно увидеть разницу текстовой версии некоторых двоичных файлов. Например, документ текстового процессора может быть преобразован в текстовое представление ASCII, и показ различий текста. Несмотря на то, что это преобразование теряет некоторую информацию, результирующая разница полезна для просмотра человеком (но не может применяться напрямую).

Параметр textconv config используется для определения программы для выполнения такого преобразования. Программа должна принимать один аргумент - имя файла для преобразования и выводить полученный текст на стандартный вывод.

Например, чтобы показать разность информации exif файла вместо двоичной информации (при условии, что у вас установлен инструмент exif), добавьте следующий раздел в свой файл. $GIT_DIR/config файл (или $HOME/.gitconfig файл):

[diff "jpg"]
        textconv = exif

Решение для mingw32, поклонникам cygwin, возможно, придется изменить подход. Проблема заключается в передаче имени файла для преобразования в cmd.exe - он будет использовать прямую косую черту, а cmd предполагает использование разделителей обратной косой черты.

Шаг 1:

Создайте сценарий с одним аргументом, который будет выполнять преобразование в стандартный вывод. C:\ путь \ к \ некоторого \script.sh:

#!/bin/bash
SED='s/\//\\\\\\\\/g'
FILE=\`echo $1 | sed -e "$SED"\`
cmd.exe /c "type $FILE"

Шаг 2:

Настройте git, чтобы иметь возможность использовать файл скрипта. Внутри вашего git config (~/.gitconfig или же .git/config или увидеть man git-config), положи это:

[diff "cmdtype"]
textconv = c:/path/to/some/script.sh

Шаг 3:

Укажите файлы, к которым можно применить этот метод, используя файлы.gitattributes (см. Man gitattributes(5)):

*vmc diff=cmdtype

затем используйте git diff в ваших файлах.

Я написал небольшой драйвер git-diff, to-utf8, что должно облегчить различие любых файлов, не кодированных в ASCII/UTF-8. Вы можете установить его, используя инструкции здесь: https://github.com/chaitanyagupta/gitutils (to-utf8 скрипт доступен в том же репо).

Обратите внимание, что этот скрипт требует как file а также iconv команды, которые будут доступны в системе.

Была ли эта проблема на Windows недавно, и dos2unixа также unix2dos бункеры, которые поставляются с мерзавцем для окон, сделали свое дело. По умолчанию они расположены в C:\Program Files\Git\usr\bin\, Заметьте, это будет работать только в том случае, если ваш файл не должен быть UTF-16. Например, кто-то случайно закодировал файл python как UTF-16, когда это не нужно (в моем случае).

PS C:\Users\xxx> dos2unix my_file.py
dos2unix: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 Unix format...

а также

PS C:\Users\xxx> unix2dos my_file.py
unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...

Как описано в других ответах, git diff не обрабатывает файлы UTF-16 как текст, и это делает их недоступными для просмотра, например, в Atlassian SourceTree. Если имя/или суффикс файла известны, приведенное ниже исправление сделает эти файлы доступными для просмотра и сравнения в обычном режиме в SourceTree.

Если суффикс файлов UTF-16 известен (например, *.uni), то все файлы с этим суффиксом могут быть связаны с преобразователем UTF-16 в UTF-8 со следующими двумя изменениями:

  1. Создайте или измените файл .gitattributes в корневом каталоге репозитория со следующей строкой:

             *.uni diff=utf16
    
  2. Затем измените файл .gitconfig в домашнем каталоге пользователя (C:\Users\yourusername\.gitconfig), указав следующий раздел:

            [diff=utf16]
        textconv = "iconv -f utf-16 -t utf-8"
    

Эти два изменения должны вступить в силу немедленно, без перезагрузки репозитория в SourceTree. Он применяет преобразование текста ко всем файлам *.uni, что делает их видимыми и сопоставимыми, как и другие текстовые файлы. Если в этом преобразовании нуждаются другие файлы, вы можете добавить дополнительные строки в файл .gitattributes. (Если указанные файлы НЕ являются UTF-16, вы получите нечитаемые результаты для этого файла.)

Обратите внимание, что этот ответ представляет собой упрощенную переработку ответа Тони Кунека.

Документация git по gitattributes дает краткое и приятное объяснение по теме кодирования -

Git распознает файлы, закодированные в ASCII или одном из его расширений (например, UTF-8, ISO-8859-1, …​), как текстовые файлы. Файлы, закодированные в некоторых других кодировках (например, UTF-16), интерпретируются как двоичные, и, следовательно, встроенные инструменты обработки текста Git (например, git diff), а также большинство веб-интерфейсов Git по умолчанию не визуализируют содержимое этих файлов.

Однакоworking-tree-encodingАтрибут позволяет указать Git, какие файлы следует перекодировать (в UTF-8) перед сохранением в репозитории. Позже они «возвращаются» к исходной кодировке при «копировании» в рабочий каталог .

Отказ от ответственности . (Возможно) все здесь было сказано в других ответах, а некоторые даже дали гораздо больше подробностей о том, как решить вашу проблему. Однако цитата, которую я включил, заставила меня понять, насколько прост ответ «Может ли Git обрабатывать кодировку, отличную от UTF-8?» после просмотра его в течение нескольких часов ...

Другие вопросы по тегам