Могу ли я заставить 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
файлы просто:
Создать
.gitattributes
файл в корне вашего хранилища с:*.strings diff=localizablestrings
Добавьте следующее к вашему
~/.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 со следующими двумя изменениями:
Создайте или измените файл .gitattributes в корневом каталоге репозитория со следующей строкой:
*.uni diff=utf16
Затем измените файл .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?» после просмотра его в течение нескольких часов ...