Как нормализовать окончания рабочих строк в Git?
Я клонировал репозиторий с несовместимыми окончаниями строк. Я добавил .gitattributes
который устанавливает атрибут текста для файлов, которые я хочу нормализовать. Теперь, когда я фиксирую изменения, я получаю сообщение:
warning: CRLF will be replaced by LF in FILE.
The file will have its original line endings in your working directory.
Как я могу заставить git нормализовать мою рабочую копию файла для меня? Желательно, чтобы git нормализовал все рабочее дерево.
8 ответов
Документация по gitattributes дает ответ:
rm .git/index # Remove the index to force git to
git reset # re-scan the working directory
git status # Show files that will be normalized
git add -u
git add .gitattributes
git commit -m "Introduce end-of-line normalization"
Сделайте эту последовательность после того, как вы отредактировали .gitattributes
,
Обновить
Похоже, у некоторых пользователей возникли проблемы с приведенными выше инструкциями. Обновленные документы для gitattributes показывают новый набор инструкций (после редактирования файлов.gitattributes):
git read-tree --empty # Clean index, force re-scan of working directory
git add .
git status # Show files that will be normalized
git commit -m "Introduce end-of-line normalization"
Спасибо vossad01 за указание на это.
Кроме того, при любом решении файлы в вашей рабочей копии по-прежнему сохраняют свои старые окончания строк. Если вы хотите обновить их, убедитесь, что ваше рабочее дерево чистое и используйте:
git rm --cached -r .
git reset --hard
Теперь окончания строк будут правильными в вашем рабочем дереве.
С клиентом Git 2.16 и выше теперь есть гораздо более простой способ сделать это. Просто используйте git add --renormalize .
Альтернативный подход (отличается только используемой командой)
Убедитесь, что в хранилище нет ожидающих изменений:
$ git status
$ git stash
изменять .gitattributes
поэтому интерпретация CRLF будет изменена:
$ echo "*.txt text" >>.gitattributes
$ git commit -m "Made .txt files a subject to CRLF normalization." -- .gitattributes
Удалить данные из индекса и обновить рабочий каталог:
$ git rm --cached -r .
$ git reset --hard
Просмотрите исправления CRLF, которые предлагает Git:
$ git ls-files --eol
$ git status
$ git diff
Согласен с Git решением:
$ git add -u
$ git commit -m "Normalized CRLF for .txt files"
Перезагрузите изменения, как если бы был сделан чистый клон:
$ git rm --cached -r .
$ git reset --hard
.gitattributes
Настройки влияют только на новые коммиты. Если в этом хранилище нет опубликованной истории (в зависимости от нее нет других), вы можете просмотреть всю историю. В Unix/Linux вы можете использовать dos2unix(1)
исправить все файлы в сочетании с find(1)
и используя переписывание истории filter-branch
(см. обсуждение в git book), вы даже можете очистить всю историю проекта.
Используйте с особой осторожностью, на свежем клоне. Свяжитесь со всеми, у кого может быть клон, и посоветуйте им, что вы хотите сделать.
Параметр * text=auto в.gitattributes оставляет репозиторий Git в "недопустимом состоянии", если он содержит файлы с окончаниями строк CRLF (Windows), которые теперь помечены как текст (см. Https://marc.info/?l=git&m=154484903528621&w=2). Стандартный вариант перенормировки не работает правильно с фильтрами LFS, поэтому инструкции в других ответах или, например, на https://help.github.com/en/articles/dealing-with-line-endings, не работают правильно. Вместо этого эти шаги сработали для нас:
Ситуация:
- В Windows
- Репозиторий Git содержал файлы с окончаниями строк CR и CRLF
- Добавлен * text=auto в.gitattributes (поэтому не зависит от пользователя, установившего core.crlf=auto в Windows)
Также изменил -crlf на -text для файлов, отслеживаемых LFS, не уверен, что это необходимо.
- Создайте новую ветку из ветки с проблемой окончания строки (при условии, что там нет незафиксированных изменений): git checkout -b feature/ Doing-stuff-fix-eol
- Удалите фильтры LFS из.gitattributes (замените все 'filter=lfs diff=lfs merge=lfs ' ничем)
- Зафиксировать и нажать: git commit -a -m "Отключить фильтры LFS для исправления EOL"
- Переместить в папку, отличную от git
- Удалите LFS глобально: git lfsuninstall
- Создайте новый клон репозитория: git clone -b feature/ Making-stuff-fix-eol [URL удаленного репозитория] fix-eol
- Нормализуйте окончания строк: git add --renormalize . (обратите внимание на точку, чтобы перенормировать все файлы)
- Проверяйте только правильные нормализованные файлы. Он не должен включать файлы, которые обычно обрабатываются LFS!
- Зафиксируйте и нажмите (сохраните хеш): git commit -m "Исправить окончания строк"
- Переместить в папку, отличную от git
- Установите LFS глобально: git lfs install
- Перейти к клону исходного репозитория и вытащить
- Оформить заказ в исходной ветке: git checkout feature/ Making-stuff
- Cherry выбирает фиксацию исправления eol и нажимает: git cherry-pick [hash]
- Удалите ветку eol и нажмите
- Удалите клон репозитория eol (или оставьте его, если вам нужно исправить больше веток)
Мне пришлось повторно клонировать репо с этим флагом
-c core.autocrlf=false
, и это сработало, никакой другой конфигурации не требуется.
Как это:
git clone -c core.autocrlf=false https://github.com/any-repo.git
Наш проект изначально был сделан с LF на Mac, но в Windows он был автоматически преобразован в CRLF. Мы используем eslint, и он подчеркивал каждую строку кода, пока я не клонировал его заново.
У меня были окончания строк CRLF в рабочем дереве и LF в репозитории, потому что папка проекта была только что скопирована с компьютера Windows на компьютер Linux с Git 1.8.3 . Вот как я сбросил окончания строк на LF:
- возвращает список всех измененных файлов
- игнорирует окончания строк и возвращает файлы, которые «действительно» изменены
-
comm -3
сравнивает списки и возвращает файлы изgit status
список которых нет вgit diff
список -
git checkout
сбрасывает эти файлы в HEAD
comm -3 <(git status --porcelain --untracked-files=no | cut -c4- | sort) <(git diff --name-only | sort) | xargs git checkout HEAD --
В merge.renormalize
настройка конфигурации может быть полезна.