Примушуйте LF eol в git repo та робочій копії


170

У мене в github знаходиться сховище git. Багато файлів спочатку були розроблені в Windows, і я не надто ретельно ставився до закінчень рядків. Коли я виконував початкову фіксацію, у мене також не було встановлено жодної конфігурації git для забезпечення правильних закінчень рядків. Підсумок полягає в тому, що в моєму сховищі github є декілька файлів із закінченнями рядків CRLF.

Зараз я частково розробляю Linux, і я хотів би очистити закінчення рядків. Як я можу переконатися, що файли зберігаються правильно з LF на github, і чи є LF у моїй робочій копії?

Я створив .gitattributesфайл, що містить text eol=LF; це правильно? З цією відданістю та наполегливістю, чи можу я просто rmсвоє місцеве репо і повторний клон з Github, щоб отримати бажаний ефект?


1
можливий дублікат git замінює LF на CRLF
Lezy Badger


Ні про те, про що я не прошу. Я єдиний розробник, і я цілком готовий налаштувати всі мої машини однаково. У мене є існуюче репо з деякими файлами CRLF, які вже прихильні до нього, та парою клонів на різних машинах. Як я можу оновлювати репо та кожну робочу копію, щоб повсюдно були LF?
Chowlett

Ви шукали цей посібник Github?
Енді

Відповіді:


237

Без трохи інформації про те, які файли є у вашому сховищі (чистий вихідний код, зображення, виконувані файли, ...), відповісти на питання трохи важко :)

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

Однак є краща альтернатива: скористайтеся кінцями рядків LF у вашому робочому колективі Linux, закінченнями рядків CRLF у вашому робочому каталозі Windows та закінченнями рядків LF у вашому сховищі.

Оскільки ви частково працюєте над Linux та Windows, переконайтеся, що core.eolвстановлено nativeта core.autocrlfвстановлено true.

Потім замініть вміст свого .gitattributesфайлу на наступне

* text=auto

Це дозволить Git обробляти автоматичне перетворення закінчень рядків для вас під час комісій та замовлень. Бінарні файли не будуть змінені, файли, виявлені як текстові файли, побачать закінчення рядків, перетворені під час руху.

Однак, як ви знаєте вміст вашого сховища, ви можете дати руку Git і допомогти йому виявити текстові файли з бінарних файлів.

Якщо ви працюєте над проектом обробки зображень на основі С, замініть вміст свого .gitattributesфайлу наступним

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

Це забезпечить збереження файлів із розширенням c, h або txt із закінченнями рядків LF у вашому репо-репортажі та матимуть нативні закінчення рядків у робочому каталозі. Файли Jpeg не торкаються. Усі інші отримають користь від тієї ж автоматичної фільтрації, що і вище.

Щоб глибше зрозуміти внутрішні деталі всього цього, я б запропонував вам зануритися в цю дуже гарну посаду "Розум кінця своєї лінії" від Тіма Клема, Гітбербера.

Як приклад із реального світу, ви також можете зазирнути на цю комісію, де .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він все ще повинен вважати робочий стіл чистим.


34
Я фактично не хочу CRLF у своїх каталогах Windows, тому що моє середовище Linux - це фактично VirtualBox, що розділяє каталог Windows; і хоча Notepad ++ тощо може працювати лише з LF у Windows, viвін менш задоволений CRLF. Я просто хочу це змінити, щоб це core.autocrlfбуло false(або input)?
Chowlett

5
Відмінна відповідь. Швидка примітка для всіх, хто використовує цю налаштування: Рядок "* text = auto" повинен бути першим рядком у вашому файлі .gitattributes, щоб наступні рядки могли перекрити це налаштування.
Арі Патрік

9
@CMCDragonkai Залежно від вашої оболонки, вона git checkout-index --force --allможе працювати краще. Другий момент виглядає трохи поза темою щодо оригінального питання. Як щодо заданого питання?
nulltoken

8
Я не розумію, чому .gitattributes не може впоратися із випадком спільного використання робочої копії між Linux та Windows. Чи не можемо ми встановити textта eol=lfдосягти такого ж результату, як описано у вашій відповіді через core.eolта core.autocrlf?
DanielSank

10
git checkout-index --force --allнічого не робить для мене. Що працює - це список команд в інструкціях GitHub для вирішення цієї проблеми.
Роман Старков

126

Починаючи з git 2.10 (вийшов 2016-09-03), не потрібно перераховувати кожен текстовий файл окремо. Git 2.10 виправляв поведінку text = auto разом з eol = lf . Джерело .

.gitattributes файл у корені вашого сховища git:

* text=auto eol=lf

Додайте та виконайте це.

Після цього ви можете виконати наступні дії, і всі файли нормалізуються зараз:

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

Джерело: Відповідь kenorb .


7
Git 2.10 вийшов 3 вересня 2016 року
стиль

Я запустив це, і це заклало всі мої текстові файли
Ентоні

Ви можете явно встановити бінарний режим для певних файлів. - Цікаво, чому автоматичне виявлення (все ще ?!) порушено на деяких файлах
koppor

Це має бути прийнятою відповіддю.
CletusW

25

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

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

що гарантує, що всі файли, які Git вважає текстовими файлами, нормалізували ( LF) закінчення рядків у сховищі (як правило, це core.eolконфігурація елементів керування, які ви маєте за замовчуванням).

Виходячи з нових параметрів атрибутів, Git повинен нормалізувати будь-які текстові файли, що містять CRLF. Якщо це не відбудеться автоматично, ви можете оновити сховище вручну після зміни закінчень рядків, так що ви можете повторно сканувати та виконувати робочий каталог, виконавши наступні кроки (задано чистий робочий каталог):

$ 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's 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

Дивитися також:


2
1. text=autoвводить в оману. Ви не можете використовувати text=autoі eolразом. Налаштування eolвимикає автоматичне виявлення текстових файлів. Ось чому вам потрібно вказати всі ці типи файлів. Якби це autoбуло ввімкнено, тобі все це не потрібно. 2. Вам не потрібно textі eol=lf. eol=lfефективно встановлює text.
Бен

2
По-друге, що сказав @Ben, ця конфігурація в даний час неправильна і небезпечна, якщо ви не позначаєте явно всі бінарні файли.
Майкл Р

1
Я читав, що * text=auto eol=lfперше text=autoперекреслено eol=lf. Де ви знайшли цю функцію? Ось мій джерело: stackoverflow.com/questions/29435156 / ...
CMCDragonkai

Вилучено * text=auto eol=lfз прикладу, оскільки він також був видалений з Drupal. Спробуйте також видалити коментарі.
kenorb

4
Важливо зауважити, що те, що сказав @Ben, більше не відповідає дійсності, і це завжди була помилка - не задумана поведінка.
Semmel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.