Какова лучшая стратегия обработки CRLF (возврат каретки, перевод строки) с Git?
Я попытался зафиксировать файлы с CRLF-концевыми строками, но это не удалось
Я провел целый рабочий день на своем компьютере с Windows, пробуя разные стратегии, и был почти не в силах прекратить попытки использовать Git и вместо этого попробовать Mercurial.
Пожалуйста, поделитесь только одним лучшим опытом для ответа.
9 ответов
Спустя почти четыре года после того, как я задал этот вопрос, я наконец нашел ответ, который меня полностью устраивает!
Подробности смотрите в github: справочное руководство по работе с окончаниями строк.
Git позволяет вам устанавливать свойства окончания строки для репо, используя атрибут text в
.gitattributes
файл. Этот файл фиксируется в репо и переопределяетcore.autocrlf
настройки, позволяющие обеспечить согласованное поведение для всех пользователей независимо от их настроек git.
И поэтому
Преимущество этого состоит в том, что ваша конфигурация конца строки теперь перемещается с вашим хранилищем, и вам не нужно беспокоиться о том, имеют ли соавторы правильные глобальные настройки.
Вот пример .gitattributes
файл
# Auto detect text files and perform LF normalization
* text=auto
*.cs text diff=csharp
*.java text diff=java
*.html text diff=html
*.css text
*.js text
*.sql text
*.csproj text merge=union
*.sln text merge=union eol=crlf
*.docx diff=astextplain
*.DOCX diff=astextplain
# absolute paths are ok, as are globs
/**/postinst* text eol=lf
# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf
Существует удобная коллекция готовых к использованию файлов.gitattributes для самых популярных языков программирования. Это полезно для начала.
Как только вы создали или скорректировали свой .gitattributes
Вы должны выполнить повторную нормализацию окончаний строки раз и навсегда.
Обратите внимание, что приложение GitHub Desktop может предложить и создать .gitattributes
файл после открытия репозитория Git вашего проекта в приложении. Чтобы попробовать это, щелкните значок шестеренки (в правом верхнем углу) > Настройки репозитория... > Концы строк и атрибуты. Вам будет предложено добавить рекомендуемые .gitattributes
и если вы согласитесь, приложение также выполнит нормализацию всех файлов в вашем хранилище.
Наконец, в статье " Разум в конце своей строки" содержится дополнительная справочная информация и объясняется, как Git развивался в рассматриваемых вопросах. Я считаю это обязательным чтением.
Возможно, в вашей команде есть пользователи, которые используют EGit или JGit (такие инструменты, как Eclipse и TeamCity используют их) для фиксации своих изменений. Тогда вам не повезло, как объясняет @gatinueta в комментариях к этому ответу:
Этот параметр не удовлетворит вас полностью, если в вашей команде есть люди, работающие с Egit или JGit, поскольку эти инструменты будут просто игнорировать.gitattributes и успешно проверять файлы CRLF https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372
Одна хитрость может заключаться в том, чтобы они зафиксировали свои изменения в другом клиенте, скажем SourceTree. Наша команда тогда предпочитала этот инструмент Eclipse EGit для многих случаев использования.
Кто сказал, что программное обеспечение легко?:-/
Не конвертируйте окончания строк. Это не работа VCS, чтобы интерпретировать данные - просто сохраните и версируйте их. Каждый современный текстовый редактор в любом случае может читать оба вида окончаний строк.
Вы почти всегда хотите autocrlf=input
если вы действительно не знаете, что делаете.
Некоторый дополнительный контекст ниже:
Должно быть либо
core.autocrlf=true
если вам нравится конец DOS илиcore.autocrlf=input
если вы предпочитаете unix-newlines. В обоих случаях ваш репозиторий Git будет иметь только LF, что является правильным. Единственный аргумент в пользуcore.autocrlf=false
было то, что автоматическая эвристика может неправильно определить некоторый двоичный файл как текст, и тогда ваша плитка будет повреждена. Так,core.safecrlf
была введена опция для предупреждения пользователя в случае необратимого изменения. На самом деле, есть две возможности необратимых изменений - смешивание конца строки в текстовом файле, при этом нормализация желательна, поэтому это предупреждение можно игнорировать или (очень маловероятно), что Git неправильно определил ваш двоичный файл как текст. Затем вам нужно использовать атрибуты, чтобы сообщить Git, что этот файл является двоичным.
Вышеупомянутый абзац был первоначально извлечен из потока на gmane.org, но с тех пор он отключился.
Две альтернативные стратегии, позволяющие добиться согласованности в окончаниях строк в смешанных средах (Microsoft + Linux + Mac):
A. Глобальная настройка для всех репозиториев
1) конвертировать все в один формат
find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
2) Установить core.autocrlf
в input
в Linux/UNIX или true
на MS Windowns (репозиторий или глобальный)
git config --global core.autocrlf input
3) [Необязательно] установить core.safecrlf
в true
(остановить) или warn
(петь:), чтобы добавить дополнительное охранное сравнение, если обратное преобразование новой строки приведет к тому же файлу
git config --global core.safecrlf true
Б. Или для каждого хранилища
1) конвертировать все в один формат
find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
2) добавить .gitattributes
файл в ваш репозиторий
echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'
Не беспокойтесь о ваших двоичных файлах - Git должен быть достаточно умным с ними.
Я потратил часы, чтобы придумать наилучшее из возможных .gitattributes
Чтобы окончательно осознать, что я не могу на это рассчитывать.
К сожалению, пока существуют редакторы на основе JGit (которые не могут обрабатывать .gitattributes
правильно), безопасное решение - заставить LF везде, даже на уровне редактора.
Используйте следующее anti-CRLF
дезинфицирующие средства.
клиенты windows / linux:
core.autocrlf=input
привержен
.gitattributes
:* text=auto eol=lf
привержен
.editorconfig
( http://editorconfig.org/), который является своего рода стандартным форматом в сочетании с плагинами редактора:
--- Обновить ---
Даже если вы не хотите использовать вышеуказанную стратегию, следующая команда - ваш друг (Примечание: в Windows клиенты работают только через git-bash
и на клиентах linux только если скомпилировано с использованием --with-libpcre
в ./configure
).
# Print all files that have been committed with CRLF (more correctly that contain CR), so that you normalize them.
git grep -I --files-with-matches --perl-regexp '\r' HEAD
Один болезненный пример:
NetBeans 8.2 (в Windows) будет некорректно фиксировать все текстовые файлы с CRLF в репо, если вы не установили явно core.autocrlf
как глобальный. Это противоречит стандартному поведению клиента git и вызывает много проблем позже при обновлении / слиянии. Это то, что заставляет некоторые файлы выглядеть по-разному (хотя это не так), даже когда вы возвращаетесь.
Такое же поведение в NetBeans происходит, даже если вы добавили правильный .gitattributes
к вашему проекту.
Использование приведенной выше команды после коммита, по крайней мере, поможет вам на раннем этапе определить, есть ли у вашего git-репо проблемы с окончанием строки.
С помощью core.autocrlf=false
прекратил помечать все файлы как обновленные, как только я проверил их в своем проекте Visual Studio 2010. Два других члена команды разработчиков также используют системы Windows, поэтому смешанная среда не вошла в игру, но настройки по умолчанию, поставляемые с хранилищем, всегда отмечали все файлы как обновленные сразу после клонирования.
Я думаю, суть в том, чтобы найти, какой параметр CRLF работает в вашей среде. Тем более что во многих других репозиториях на наших установках Linux ящики autocrlf = true
дает лучшие результаты.
Спустя 20 с лишним лет, и мы все еще имеем дело с разницей в конце строк между операционными системами... грустно.
Попробуйте установить core.autocrlf
опция конфигурации для true
, Также посмотрите на core.safecrlf
вариант.
На самом деле это звучит как core.safecrlf
может быть уже установлен в вашем хранилище, потому что (выделение мое):
Если это не относится к текущим настройкам core.autocrlf, git отклонит файл.
Если это так, то вы можете проверить, что ваш текстовый редактор настроен на последовательное использование концов строк. Скорее всего, вы столкнетесь с проблемами, если текстовый файл будет содержать сочетания концов строк LF и CRLF.
Наконец, я чувствую, что рекомендация просто "использовать то, что вам дано" и использовать строки с ограничением LF в Windows, вызовет больше проблем, чем решит. У Git есть вышеупомянутые опции, чтобы попытаться обработать окончания строк разумным способом, поэтому имеет смысл использовать их.
Это две опции для пользователей Windows и Visual Studio, которые делятся кодом с пользователями Mac или Linux. Для подробного объяснения прочитайте руководство по gitattributes.
* текст = авто
В вашем репо .gitattributes
добавление файла:
* text=auto
Это нормализует все файлы с LF
окончания строк в репо.
И в зависимости от вашей операционной системы (core.eol
настройки), файлы в рабочем дереве будут нормализованы к LF
для систем на базе Unix или CRLF
для систем Windows.
Это конфигурация, которую используют репозитории Microsoft .NET.
Пример:
Hello\r\nWorld
Будет нормализован в репо всегда так:
Hello\nWorld
При оформлении заказа рабочее дерево в Windows будет преобразовано в:
Hello\r\nWorld
На кассе рабочее дерево в Mac останется как:
Hello\nWorld
Примечание. Если репозиторий уже содержит файлы, которые не были нормализованы,
git status
эти файлы будут полностью изменены в следующий раз, когда вы внесете в них какие-либо изменения, и другим пользователям будет неудобно объединять их изменения позже. См. Обновление хранилища после изменения концов строк для получения дополнительной информации.
core.autocrlf = true
Если text
не указано в .gitattributes
Git использует core.autocrlf
переменная конфигурации, чтобы определить, должен ли файл быть преобразован.
Для пользователей Windows, git config --global core.autocrlf true
отличный вариант, потому что:
- Файлы нормализованы до
LF
окончания строк только при добавлении в репо. Если в репо есть файлы, которые не нормализованы, этот параметр не коснется их. - Все текстовые файлы конвертируются в
CRLF
окончания строк в рабочем каталоге.
Проблема с этим подходом заключается в том, что:
- Если вы пользователь Windows с
autocrlf = input
, вы увидите кучу файлов сLF
окончания строки. Не представляет опасности для остальной части команды, потому что ваши коммиты все равно будут нормализованы сLF
окончания строки. - Если вы пользователь Windows с
core.autocrlf = false
, вы увидите кучу файлов сLF
окончания строк, и вы можете ввести файлы сCRLF
Концы строк в репо. - Большинство пользователей Mac используют
autocrlf = input
и может получить файлы сCRLF
окончания файлов, вероятно, от пользователей Windows сcore.autocrlf = false
,
Это просто обходное решение:
В обычных случаях используйте решения, которые поставляются с git. Они прекрасно работают в большинстве случаев. Принудительно LF, если вы делитесь разработкой в системах на базе Windows и Unix, устанавливая .gitattributes.
В моем случае>10 программистов разрабатывали проект в Windows. Этот проект был проверен с CRLF, и не было никакой возможности, чтобы заставить LF.
Некоторые настройки были написаны на моем компьютере без какого-либо влияния на формат LF; таким образом, некоторые файлы глобально менялись на LF при каждом небольшом изменении файла.
Мое решение:
Windows-машины: пусть все как есть. Ничего не волнует, так как вы являетесь разработчиком окон "одинокий волк" по умолчанию, и вам приходится обращаться с этим так: "В широком мире нет другой системы, не так ли?"
Unix-машины
Добавьте следующие строки в конфиг
[alias]
раздел. Эта команда выводит список всех измененных (т.е. измененных / новых) файлов:lc = "!f() { git status --porcelain \ | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \ | cut -c 4- ; }; f "
Преобразуйте все эти измененные файлы в формат DOS:
unix2dos $(git lc)
По выбору...
Создайте git hook для этого действия, чтобы автоматизировать этот процесс
Используйте параметры и включите их и измените
grep
функция для соответствия только определенным именам файлов, например:... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
Не стесняйтесь делать это еще удобнее, используя дополнительный ярлык:
c2dos = "!f() { unix2dos $(git lc) ; }; f "
... и запустить преобразованный материал, набрав
git c2dos