Но мои файлы по-прежнему имеют конец строки CRLF.
Если файл внутри коммита внутри репозитория имеет окончания строк CRLF, эта версия этого файла застрянет таким образом навсегда , Никакая часть какого-либо существующего коммита не может быть изменена.
Если файл внутри коммита внутри репозитория имеет окончания строк только для LF, эта версия этого файла застрянет таким образом навсегда. Тем не менее, вы можете можете выбрать окончание, которое вы хотите иметь Git место в вашем рабочем дереве при извлечении этого файла.
Если вы уже распаковали файл , Git уже сделал преобразование. Git теперь думает, что все в порядке, даже если вы только что изменили настройку преобразования.
Таким образом, если вы измените настройку преобразования, вы должны заставить Git повторно извлечь файл. Самый простой способ сделать это последовательно во всех версиях Git - это удалить файл из вашего рабочего дерева, а затем запустить git checkout -- <em>path/to/file</em>
. Поскольку файл удален из рабочего дерева, Git будет вынужден снова извлечь его. На этот раз будет применено обновленное EOL-преобразование.
(Другой способ сделать это - изменить файл, а затем запустить тот же git checkout
, либо в Git 2.23 или более поздней версии, чтобы использовать git restore
. Говоря Git, что Git должен отбросить вашу версию файла, и Git, увидев, что ваша версия файла действительно "неправильная" в том, что она не соответствует копии индекса, потому что вы изменили ее, Git будет вынужден повторно извлечь индексную копию.)
Это может быть достаточно для вашего случая, а может и нет. Если это не так, читайте дальше.
Что нужно знать о преобразованиях конца строки в Git
Я твердо верю в "никогда не используйте Windows в все для того, чтобы вам никогда не приходилось гадить на вашей системе контроля версий с окончаниями строк. «Философия сама, но есть несколько вещей, которые нужно знать, если вы находитесь в каком-то другом лагере и do хотите, чтобы Git гадили с окончания строки. Наиболее важными из них являются следующие: То, что вы храните в Git, и то, что вы используете при работе с файлами, которые вы получили из из Git, не являются обязательно то же самое.
Чтобы увидеть, как это работает, помните, что Git хранит коммитов вместо непосредственного хранения файлов. Файлы внутри этих коммитов поступают из Git index , а не из вашего рабочего дерева. Формат индексной копии файла совпадает с внутренним форматом, который Git использует для фиксации на все время: данные предварительно сжаты. Таким образом, копия каждого файла в индексе уже значительно отличается от копии, которую вы используете в своем рабочем дереве, в том смысле, что копия в вашем рабочем дереве не является объектом Git blob и, как правило, не сжата zlib.
Git читает коммиты в индекс, прежде чем копировать их в ваше рабочее дерево. Запуск git add
для файла сжимает и помещает файл в BLOB-файл, чтобы сохранить его в индексе Git. Прямо в этой точке преобразования , в то время как Git сжимает и Git - уточняет файл (git add
) или de- Git - уточняет и распаковывает файл (git checkout-index
или эквивалентный) ), Git просто вставить дополнительные операции преобразования.
Git поэтому делает свое дело на этом этапе. Вещи, которые Git может сделать - только , встроенные напрямую - в том, что на пути из индекса Git может заменить \n
-только строку окончания с \r\n
окончаниями строк и по пути в указатель, Git могут заменить \r\n
окончания строк \n
только окончаниями строк.
Другими словами Вы можете организовать Git до выбрасывания некоторых возвратов каретки перед сохранением файла и добавления возвратов некоторых карет при извлечении файл. Если вы выполните оба этих действия, вы получите окончания строк CRLF в вашем рабочем дереве и окончания строк только для новой строки в фиксациях.
Вы можете, если хотите, Git сделать только один из них: в частности, с настройкой crlf=input
вы можете сказать Git: сделать только одно преобразование , в операции копирования дерево-в-индекс.
Если вы выбираете Git делать преобразования при извлечении файлов, только преобразование, доступное здесь, составляет превратить LF-only в CRLF . Вы не можете превратить окончания CRLF в окончания только LF. Если файл in- Git commit имеет окончания CRLF, извлеченный файл в рабочем дереве будет иметь окончания CRLF.
Опять же, каждое из этих преобразований происходит только в одном направлении:
- index → work-tree: опционально, заменить
\n
на \r\n
- work-tree → index: опционально, заменить
\r\n
на \n
То, что вы выбираете с помощью директив core.autocrlf
или .gitattributes
:
text
, -text
и / или core.autocrlf
: какие файлы eol=...
и / или core.eol
: узнать, какие обработки crlf=input
: какие операции
После обработки файла и преобразованный - путем копирования его в индекс или из индекса - Git помечает копию индекса как «совпадающую с копией рабочего дерева», получая данные ключа из ОС: размер файла и другие значения lstat
системных вызовов. Точные подробности здесь различаются, потому что разные ОС хранят разные данные с разной степенью детализации.
Простой способ заставить новое преобразование - удалить одну или другую копию файла: rm file
или git rm --cached file
уничтожает рабочее дерево или индексная копия соответственно, поэтому теперь git checkout -- file
или git add file
создаст новый.
При запуске git commit
все байты в копии index файла go в новый коммит, который Git делает. Этот новый коммит теперь заморожен на все времена: байты, которые были в индексе, теперь находятся в коммите, навсегда (или до тех пор, пока сам коммит продолжает существовать). Ничто и никто не может их изменить.
Последствия вышеперечисленного
Что означает вышеизложенное, это то, что если вы do планируете иметь свою систему контроля версий (то есть, Git) разбираться с окончаниями строк, окончаниями строк, которые вы можете - и, следовательно, вероятно, должны - всегда использовать для каждой индексной копии , и, следовательно, каждой подтвержденной копии , каждого текстового файла являются LF-только окончания строк. Они всегда могут быть преобразованы в окончания CRLF в файле рабочего дерева с помощью соответствующей настройки .gitattributes
или core.*
. Если вы сделали такое преобразование, этот файл рабочего дерева можно преобразовать обратно в окончания строк только для LF при операциях git add
.
Если вы когда-либо сделаете commit файл с Концы строк CRLF, этот коммит застревает таким образом на все времена, и извлечение этого коммита каждый раз даст вам копию рабочего дерева с окончаниями строк CRLF, потому что Git не имеет встроенного индекса → работа с деревом, которая изменит это. Единственная встроенная операция CRLF-to-LF, которую имеет Git, работает только в другом направлении, индекс ← рабочее дерево.
Если вы хотите сделать новый и улучшенный коммит, в котором зафиксированный копия этого файла имеет только LF-окончания, у вас есть две опции:
- , убедитесь, что ваши настройки индекса ← ← дерево работ, делает это, а затем Git, чтобы добавить файл (например, измените его в рабочем дереве или используйте
git rm --cached
для индексной копии и git add
это); или - используйте любую команду, которая изменяет копию рабочего дерева, чтобы иметь окончания строки только для LF, например, запустите на нем
dos2unix
или аналогичный, затем git add
it.
Преимущество метода 2 заключается в том, что вы можете видеть эффект немедленно (в файле рабочего дерева), и его трудно понять неправильно. Проблема с методом 1 заключается в том, что вы не можете увидеть его, и легко получить его полностью неправильно: например, вы можете случайно использовать git rm
вместо git rm --cached
, который удаляет оба индекса и копии рабочего дерева.