Как настроить новый репозиторий git для смешанных файлов LF/CRLF

Я использую GitHub Desktop на Windows 10. Я хочу установить git-репозиторий, который будет содержать некоторые текстовые файлы (.md или.adoc) и Freemind mindmaps (.mm). Freemind использует формат файла на основе XML с переводом строки в стиле Unix (LF).

За последние 4 часа, я думаю, что я прочитал все обсуждения Stackru и каждую git-документацию по нормализации EOL, которую можно найти в Интернете - и это все еще сводит меня с ума! Многие дискуссии кажутся устаревшими, а мнения противоречат друг другу. Вот как я дошел до этого:

  • я ушел core.autocrlf а также core.safecrlf на их значения по умолчанию
  • Как рекомендую я использую .gitattributes файл с * text=auto - Я в порядке с автоматическим преобразованием для моих текстовых файлов.
  • Чтобы сохранить LF моих файлов.mm, которые я добавил *.mm text eol=LF

Что меня озадачивает, так это предупреждение:

> git add Mindmap.mm
warning: LF will be replaced by CRLF in Mindmap.mm.
The file will have its original line endings in your working directory.

Насколько я понимаю * text=auto эквивалентно core.autocrlf=true и гарантирует, что все EOL будут преобразованы в LF при фиксации - поэтому LF->LF в этом случае. А также *.mm text eol=LF обеспечивает сохранение LF при оформлении заказа - LF->LF и в другом направлении. Никакой CRLF не участвует! Так почему же Git предупреждает меня, что какое-то преобразование приведет к CRLF?

Вопрос 1: Я хотел бы убедиться, что у меня не возникнет кроссплатформенных проблем с пользователями UNIX, когда я открою свой проект на GitHub. Какова лучшая практика для моего случая? Если я все сделал правильно, могу ли я проигнорировать предупреждение?

Вопрос 2: При определенных обстоятельствах.mm файлы могут также содержать CRLF. Конечно, я мог бы обрабатывать их как двоичные файлы, но тогда я больше не видел бы различий в GitHub Desktop. Есть ли способ обрабатывать их как текстовые файлы, сохраняя при этом смешанные переводы строк (LF и CRLF)?

Любая подсказка очень ценится!

2 ответа

Я не использую Windows, и поэтому немного стесняюсь давать рекомендации, но я могу описать здесь различные механизмы и сделать хотя бы несколько.:-)

Операции, которые преобразуют данные файла, включая все, что изменяет окончания строк, применяются (в общем случае, если есть некоторые конкретные исключения) во время извлечения данных из репозитория в рабочее дерево - это в основном git checkout, но посмотрите примечания к концу - или добавьте в хранилище, которое в основном git add,

Чтобы преобразовать данные файла, Git должен знать, какие файлы преобразуются, а какие - применять. Git должен классифицировать каждый файл, чтобы решить, что делать.

Некоторые файлы явно двоичные, некоторые почти наверняка текстовые, а некоторые довольно неоднозначные. Git будет догадываться, если это необходимо. Вы можете (и я думаю, возможно, раньше приходилось?) Сказать это угадать, установив core.autocrlf=true или же core.autocrlf=input, но смотри следующий абзац.

Если у тебя есть .gitattributes файл, вы можете сказать Git о файлах на основе их путей, например, что *.txt всегда должны рассматриваться как текстовые файлы и *.bin файлы никогда не должны рассматриваться как текстовые файлы. Это дает вам гораздо более точный контроль, потому что вы можете не только сопоставлять, основываясь на таких путевых именах, вы также можете написать любой из них:

*.ex1   text      # definitely text
*.ex2   -text     # definitely not text
*.ex3   text=auto # please guess for me based on file contents
# don't mention *.ex4: check core.autocrlf to decide whether to guess

Основываясь на этой части, я бы предложил core.autocrlf никогда не бывает полезным, потому что гадание кажется подозрительным. По крайней мере с text=auto у вас есть очевидное место, запрашивающее догадки, хотя.

Независимо от предположения или определенного, вы можете перечислить eol=crlf или же eol=lf после пути. Это позволяет преобразование, т. Е. Файл обрабатывается так, как если бы он был текстом, когда дело доходит до решения, связываться с окончаниями строк при извлечении git checkout) и вставка (git add). В рабочем дереве появляется либо CRLF, либо только LF. В любом случае CRLF в рабочем дереве заменяется на LF-only во время git add, Я подозреваю, но не проверял, что это не влияет git diff,

(Старый crlf, -crlf, а также crlf=input настройки, несомненно, больше не должны использоваться, но если вы их используете, они действуют, как описано в gitattributes документация.)

Теперь очевидная проблема, которую вы подчеркнули, заключается в том, что с помощью -text чтобы пометить файл как "никогда не трогать autocrlf или другие предполагаемые преобразования" взаимодействует с git diff, так как git diff также должен угадать, является ли файл текстовым, перед созданием diff. Здесь мы можем вернуться к gitattributes документация, где мы находим, что пути могут иметь diff атрибут:

*.ex5   -text diff  # not text for crlf treatment, but text for diff
*.ex6   -text -diff # not text for either one
*.ex7   text -diff  # definitely text for crlf, but binary for diff
*.ex8   diff=my-diff-driver # use my diff driver; no opinion about text

Покидать diff полностью заставляет Git догадываться, так же как и в случае с crlf-обработкой.

Обратите внимание, что имена путей в .gitattributes не должно быть шаблонов: вы можете перечислить:

path/to/some/file       -text
path/to/another/file    text

в случае, если Git неправильно угадывает некоторые файлы.

Я еще не упомянул core.safecrlf но я думаю, что обсуждение в git config документация вполне адекватна здесь. Он состоит из набора специальных тестов, запускаемых во время выполнения различных команд, причем преобразования в обоих направлениях выполняются немного раньше, а на последнем этапе проверки происходит переход к временному файлу, который немедленно выбрасывается, просто чтобы посмотреть, есть ли файлы в рабочем дереве. Прямо сейчас останется таким, какой они есть сейчас. То есть, если вы сделали git add path; git commit -m dummy; rm path; git checkout -- path щас изменится ли содержимое файла в пути? Если это так, преобразование не является "безопасным".

Наконец, я должен упомянуть еще несколько особых случаев. Преобразования (как окончания строк, так и грязные фильтры) выполняются каждый раз, когда файл выходит из индекса; это включает в себя git checkout-index команда. Они также могут быть сделаны специально во время операций, которые обходят индекс: git cat-file, добавляя --textconv или же --path= или же --filters; git show, с --textconv, хотя детали немного различаются в зависимости от конкретной версии Git (многие из этих опций недоступны в более старых версиях Git). Аналогично, преобразования (окончания строк и чистые фильтры) выполняются каждый раз, когда файл попадает в индекс, но также могут выполняться или подавляться в git hash-object, с помощью --path или же --no-filters,

Отключение text за .mm файлы будут мешать Git делать crlf преобразования, но он не начнет обрабатывать их как двоичные файлы, поэтому git-diff и другие функции будут работать правильно.

В вашем файле.gitattributes:

* text=auto

*.mm -text

Это должно решить ваш второй вопрос. Тем не менее, потому что Git не будет обеспечивать окончания строки для .mm файлы, вероятно, вызовут некоторые головные боли, когда вы станете публичными, и участники начнут изменять их в OS-X и Linux. Если вы можете описать правила для .mm окончания строк, может быть, конфигурация может быть изменена, или, возможно, фиксация коммитов может помочь вам обеспечить ее выполнение, кроме того, я не понимаю, как вы можете решить свои первый и второй вопросы одновременно.

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