Как нормализовать окончания рабочих строк в 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, не уверен, что это необходимо.

    1. Создайте новую ветку из ветки с проблемой окончания строки (при условии, что там нет незафиксированных изменений): git checkout -b feature/ Doing-stuff-fix-eol
    2. Удалите фильтры LFS из.gitattributes (замените все 'filter=lfs diff=lfs merge=lfs ' ничем)
    3. Зафиксировать и нажать: git commit -a -m "Отключить фильтры LFS для исправления EOL"
    4. Переместить в папку, отличную от git
    5. Удалите LFS глобально: git lfsuninstall
    6. Создайте новый клон репозитория: git clone -b feature/ Making-stuff-fix-eol [URL удаленного репозитория] fix-eol
    7. Нормализуйте окончания строк: git add --renormalize . (обратите внимание на точку, чтобы перенормировать все файлы)
    8. Проверяйте только правильные нормализованные файлы. Он не должен включать файлы, которые обычно обрабатываются LFS!
    9. Зафиксируйте и нажмите (сохраните хеш): git commit -m "Исправить окончания строк"
    10. Переместить в папку, отличную от git
    11. Установите LFS глобально: git lfs install
    12. Перейти к клону исходного репозитория и вытащить
    13. Оформить заказ в исходной ветке: git checkout feature/ Making-stuff
    14. Cherry выбирает фиксацию исправления eol и нажимает: git cherry-pick [hash]
    15. Удалите ветку eol и нажмите
    16. Удалите клон репозитория 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 настройка конфигурации может быть полезна.

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