Сила LF eol в репозитории git и рабочая копия

У меня есть репозиторий git, размещенный в github. Многие из файлов были первоначально разработаны в Windows, и я не слишком осторожно относился к окончанию строк. Когда я выполнил начальную фиксацию, у меня также не было никакой конфигурации git, чтобы обеспечить правильные окончания строк. Результатом является то, что у меня есть несколько файлов с концами строк CRLF в моем репозитории github.

Сейчас я частично разрабатываю Linux, и я бы хотел очистить концы строк. Как я могу гарантировать, что файлы правильно сохранены с LF на github и имеют LF в моей рабочей копии?

Я установил файл .gitattributes, содержащий text eol=LF; это верно? С помощью этого совершенного и нажатого я могу просто rm локальное репо и повторное клонирование из github, чтобы получить желаемый эффект?

Ответ 1

Без небольшой информации о том, какие файлы находятся в вашем репозитории (чистый исходный код, изображения, исполняемые файлы,...), немного сложно ответить на вопрос:)

Кроме того, я буду считать, что вы готовы по умолчанию использовать LF в качестве окончаний строки в вашем рабочем каталоге, потому что вы готовы убедиться, что текстовые файлы имеют окончания строки LF в вашем репозитории .git, если вы работаете Windows или Linux. Действительно лучше безопасно, чем жаль....

Тем не менее, есть лучшая альтернатива: Воспользуйтесь концами строк LF в вашем рабочем столе Linux, окончаниями строк CRLF в конце концов Windows Workdir и LF в вашем репозитории.

Поскольку вы частично работаете с Linux и Windows, убедитесь, что для параметра core.eol установлено значение native и core.autocrlf установлено значение true.

Затем замените содержимое вашего файла .gitattributes следующим

* text=auto

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

Однако, поскольку вы знаете содержимое своего репозитория, вы можете дать Git руку и помочь ему обнаруживать текстовые файлы из двоичных файлов.

Если вы работаете над проектом обработки изображений на основе C, замените содержимое вашего файла .gitattributes на следующие

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

Это позволит убедиться, что файлы, расширение которых c, h или txt, будут сохранены с окончанием строки LF в вашем репо и будут иметь собственные окончания строк в рабочем каталоге. Файлы Jpeg не будут затронуты. Все остальные получат выгоду от такой же автоматической фильтрации, как показано выше.

Чтобы получить более глубокое понимание внутренних деталей всего этого, я бы посоветовал вам погрузиться в этот очень хороший пост "Запомните конец вашей линии" от Тима Клема, Githubber.

В качестве примера в реальном мире вы также можете посмотреть на commit, где показаны эти изменения в файле .gitattributes.

ОБНОВЛЕНИЕ к ответу с учетом следующего комментария

Я действительно не хочу CRLF в своих каталогах Windows, потому что моя Linux-среда фактически является VirtualBox, совместно использующим каталог Windows

Имеет смысл. Спасибо за разъяснения. В этом конкретном контексте файл .gitattributes сам по себе не будет достаточным.

Запустите следующие команды в своем репозитории

$ git config core.eol lf
$ git config core.autocrlf input

Поскольку ваш репозиторий разделяется между вашей Linux и средой Windows, это обновит локальный файл конфигурации для среды. core.eol будет следить за тем, чтобы в текстовых файлах были завершены окончания строки LF. core.autocrlf гарантирует, что потенциальный CRLF в текстовых файлах (в результате операции копирования/вставки, например) будет преобразован в LF в вашем репозитории.

По желанию вы можете помочь Git отличить текстовый файл, создав файл .gitattributes, содержащий что-то похожее на следующее:

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

Если вы решили создать файл .gitattributes, зафиксировать его.

Наконец, убедитесь, что git status упоминает "ничего не зафиксировать (рабочий каталог не чист)", затем выполните следующую операцию

$ git checkout-index --force --all

Это приведет к восстановлению ваших файлов в вашем рабочем каталоге с учетом ваших изменений конфигурации и файла .gitattributes и замены любого потенциально недопустимого CRLF в ваших текстовых файлах.

Как только это будет сделано, каждый текстовый файл в вашем рабочем каталоге будет содержать окончание строки LF, а git status должен по-прежнему считать рабочий диск чистым.

Ответ 2

Чтобы заставить конец строки LF для всех текстовых файлов, вы можете создать .gitattributes файл на верхнем уровне вашего репозитория со следующим линии (по желанию):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

который гарантирует, что все файлы, которые Git считает текстовыми файлами, имеют нормализованные (LF) окончания строки в репозитории (обычно core.eol элементы управления конфигурацией, которые вы по умолчанию).

На основе новых настроек атрибута любые текстовые файлы, содержащие CRLF, должны быть нормализованы с помощью Git. Если это не произойдет автоматически, вы можете обновить репозиторий вручную после изменения окончаний строки, так что вы можете повторно сканировать и зафиксировать рабочий каталог следующими шагами (с учетом чистой рабочей директории):

$ 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"

или согласно Документы GitHub:

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

См. также: @Charles Bailey post.

Кроме того, если вы хотите исключить любые файлы, которые не обрабатываются как текст, отключите их текстовый атрибут, например.

manual.pdf      -text

Или пометить его явно как двоичный:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

Чтобы увидеть более продвинутый файл нормализации Git, отметьте .gitattributes в Ядро Drupal:

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

См. также:

Ответ 3

Начиная с git 2.10, нет необходимости перечислять каждый текстовый файл отдельно. git 2.10 исправлено поведение text = auto вместе с eol = lf. Источник.

.gitattributes в корневом каталоге репозитория git:

* text=auto eol=lf

Добавить и зафиксировать его.

После этого вы можете выполнить следующие шаги, и теперь все файлы нормализованы:

git rm --cached -r .  # Remove every file from git index.
git reset --hard      # Rewrite git index to pick up all the new line endings.

Источник: Ответа на этот вопрос kenorb.