Попытка исправить линейные окончания с помощью git filter-branch, но не повезло

Я был укушен выпуском Windows/Linux с окончанием строки git. Кажется, с помощью GitHub, MSysGit и других источников лучшее решение состоит в том, чтобы установить локальные репозитории на использование окончаний строк в стиле Linux, но установите core.autocrlf на true. К сожалению, я не делал этого достаточно рано, так что теперь, каждый раз, когда я вытягиваю изменения, концы строк срываются.

Мне показалось, что я нашел ответ здесь, но я не могу заставить его работать для меня. Мои знания командной строки в Linux ограничены в лучшем случае, поэтому я даже не уверен, что делает строка "xargs fromdos" в своем script. Я продолжаю получать сообщения о отсутствии такого файла или каталога, и когда мне удаётся указать его на существующий каталог, он говорит мне, что у меня нет разрешений.

Я пробовал это с MSysGit в Windows и с помощью терминала Mac OS X.

Ответы

Ответ 1

Документация git для gitattributes теперь документирует другой подход для "исправления" или нормализации всех концов строк в вашем проекте. Вот его суть:

$ echo "* text=auto" >>.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"

Если какие-либо файлы, которые не должны быть нормализованные отображаются в статусе git, отключить свой текстовый атрибут до запуск git add -u.

manual.pdf -text

И наоборот, текстовые файлы, которые gitне обнаружение может иметь нормализацию разрешено вручную.

weirdchars.txt text

Ответ 2

Самый простой способ исправить это - сделать одну фиксацию, которая исправляет все окончания строк. Предполагая, что у вас нет модифицированных файлов, вы можете сделать это следующим образом.

# From the root of your repository remove everything from the index
git rm --cached -r .

# Change the autocrlf setting of the repository (you may want 
#  to use true on windows):
git config core.autocrlf input

# Re-add all the deleted files to the index
# (You should get lots of messages like:
#   warning: CRLF will be replaced by LF in <file>.)
git diff --cached --name-only -z | xargs -0 git add

# Commit
git commit -m "Fixed crlf issue"

# If you're doing this on a Unix/Mac OSX clone then optionally remove
# the working tree and re-check everything out with the correct line endings.
git ls-files -z | xargs -0 rm
git checkout .

Ответ 3

Моя процедура обработки окончаний строки следующая (битва протестирована во многих репозиториях):

При создании нового репо:

  • поместите .gitattributes в первую фиксацию вместе с другими типичными файлами как .gitignore и README.md

При работе с существующим репо:

  • Создать/изменить .gitattributes соответственно
  • git commit -a -m "Modified gitattributes"
  • git rm --cached -r . && git reset --hard && git commit -a -m 'Normalize CRLF' -n"
    • -n (--no-verify - пропустить предварительные фиксации)
    • Я должен делать это достаточно часто, чтобы определить его как псевдоним alias fixCRLF="..."
  • повторить предыдущую команду
    • yep, это voodoo, но обычно мне нужно запустить команду дважды, сначала нормализует некоторые файлы, второй раз - еще больше файлов. Обычно лучше всего повторять до тех пор, пока не будет создана новая фиксация:)
  • вернуться назад и вперед между старым (как раз перед нормализацией) и новой ветвью несколько раз. После переключения ветки иногда git найдет еще больше файлов, которые необходимо перенормировать!

В .gitattributes я объявляю все текстовые файлы явно LF EOL , так как обычно инструменты Windows совместимы с LF, в то время как инструменты, отличные от Windows, не совместимы с CRLF (даже многие инструменты командной строки nodejs предполагают LF и, следовательно, может изменить EOL в ваших файлах).

Содержимое .gitattributes

Мой .gitattributes обычно выглядит так:

*.html eol=lf
*.js   eol=lf
*.json eol=lf
*.less eol=lf
*.md   eol=lf
*.svg  eol=lf
*.xml  eol=lf

Чтобы выяснить, какие отдельные расширения отслеживаются git в текущем репо, смотрите здесь

Проблемы после нормализации

Как только это будет сделано, есть еще одно общее предупреждение.

Скажите, что ваш master уже обновлен и нормализован, а затем вы проверите outdated-branch. Довольно часто сразу после проверки этой ветки, git отмечает, что многие файлы изменены.

Решение состоит в том, чтобы выполнить фальшивый коммит (git add -A . && git commit -m 'fake commit'), а затем git rebase master. После перезагрузки фальшивая фиксация должна исчезнуть.

Ответ 4

git status --short|grep "^ *M"|awk '{print $2}'|xargs fromdos

Пояснение:

  • git status --short

    Здесь отображается каждая строка, в которой git есть и не известно. Файлы, которые не находятся под управлением git, отмечены в начале строки символом "?". Измененные файлы отмечены знаком M.

  • grep "^ *M"

    Отфильтровывает только те файлы, которые были изменены.

  • awk '{print $2}'

    Это показывает только имя файла без каких-либо маркеров.

  • xargs fromdos

    Это принимает имена файлов из предыдущей команды и запускает их через утилиту 'fromdos' для преобразования строк.

Ответ 5

"| xargs fromdos" читается со стандартного ввода (файлы find находит) и использует его в качестве аргументов для команды fromdos, которая преобразует окончание строки. (Является стандартом fromdos в тех средах? Я привык к dos2unix). Обратите внимание, что вы можете избежать использования xargs (особенно полезно, если у вас достаточно файлов, для которых список аргументов слишком длинный для xargs):

find <path, tests...> -exec fromdos '{}' \;

или

find <path, tests...> | while read file; do fromdos $file; done

Я не совсем уверен в ваших сообщениях об ошибках. Я успешно протестировал этот метод. Какая программа производит каждый? В каких файлах/каталогах у вас нет разрешений? Тем не менее, вот удар, угадающий, каково ваше бытие:

Один простой способ получить ошибку "файл не найден" для script заключается в использовании относительного пути - используйте абсолютный. Аналогично, вы можете получить ошибку разрешений, если вы не выполнили свой исполняемый файл script (chmod + x).

Добавьте комментарии, и я попытаюсь помочь вам в этом!

Ответ 6

okay... под cygwin у нас нет доступных todos, и что awk substeb взорвется вам в лицо, если у вас есть пробелы в пути к модифицированным файлам (что у нас было), поэтому мне пришлось сделать это несколько иначе:

git status --short | grep "^ *M" | sed 's/^ *M//' | xargs -n 1 dos2unix

kudos для @lloyd для основной части этого решения

Ответ 7

Вот как я зафиксировал все окончания строк во всей истории, используя git filter-branch. Символу ^M необходимо ввести с помощью CTRL-V + CTRL-M. Я использовал dos2unix для преобразования файлов, так как это автоматически пропускает двоичные файлы.

$ git filter-branch --tree-filter 'grep -IUrl "^M" | xargs -I {} dos2unix "{}"'

Ответ 8

Выполните следующие действия, если ни один из других ответов не будет работать для вас:

  • Если вы находитесь в Windows, выполните git config --global core.autocrlf true; если вы находитесь в Unix, выполните git config core.autocrlf input
  • Запустить git rm --cached -r .
  • Удалить файл .gitattributes
  • Запустить git add -A
  • Выполнить git reset --hard

Затем ваш локальный должен быть чистым.