Вместо прямого ответа на сам вопрос — см. ответ VonC на связанный вопрос — давайте сосредоточимся на этом:
В настоящее время у меня есть репозиторий с несколькими поврежденными файлами, которые я хочу преобразовать в представление crlf.
Во-первых, отметим, что ни один из этих параметров не может изменить любую существующую фиксацию. Это фундаментальное свойство Git: однажды созданный коммит нельзя изменить. Что вы можете сделать, так это сделать новые коммиты. Обычно это не имеет большого значения, поскольку обычно мы просто хотим, чтобы новые вещи были правильными (но см. git filter-branch
, который копирует коммиты после применения фильтров к их содержимому и может использоваться для повторного копирования всего репозитория). : новое репо больше не совместимо со старым, но таким образом можно "исправить историю").
Далее, я думаю, что это ключ к пониманию всех этих вариантов атрибутов конца строки / CRLF: преобразования применяются к файлам, когда они перемещаются в индекс или из него.
Помните, что индекс Git — это место, где вы создаете следующий коммит. Содержимое индекса изначально такое же, как и любая текущая фиксация: например, вы запускаете git checkout master
, а Git разрешает имя master
в идентификатор фиксации и копирует эту конкретную фиксацию в ваше рабочее дерево, но копия идет через индекс.
Другими словами, Git сначала находит файл foo.txt
в коммите (и его нужно извлечь). Поэтому Git перемещает эту версию foo.txt
в индекс. Версия индекса точно совпадает с версией HEAD
фиксации. Git не применяет никаких фильтров к индексной версии и не изменяет окончания строк.
После обновления версии индекса Git копирует эту версию файла из индекса в рабочее дерево.1 Происходят некоторые преобразования < em>сейчас во время этого процесса извлечения. Если есть фильтр размытия, Git применяет его сейчас. Если необходимо выполнить преобразования конца строки, Git применяет их сейчас.
Во время этого процесса файл рабочего дерева может отличаться от версии индекса. Теперь у Git есть проблема, потому что теперь файл «грязный» (измененный в рабочем дереве). Здесь все становится особенно запутанным, хотя в большинстве случаев детали здесь невидимы.
В конце концов, после работы с вашим рабочим деревом вы можете запустить git add
для некоторого пути к файлу (или использовать git add -a
или что-то еще, чтобы добавить много файлов). Это копирует файл из рабочего дерева в индекс.2 Теперь во время этого копирования происходят дополнительные преобразования: если есть чистый фильтр, Git применяет его сейчас. Если необходимо выполнить преобразования конца строки, Git применяет их сейчас.
Другими словами, после git add
создания этих файлов версия индекса может не совпадать с версией рабочего дерева. Однако Git все равно помечает индексную версию как «соответствующую». git status
пропустит сразу версию рабочего дерева, потому что Git теперь утверждает, что версия индекса соответствует версии рабочего дерева. В некотором роде это так, потому что версия индекса совпадает с той, что была бы добавлена, если бы вы снова запустили git add
.
Фактическая реализация использует метки времени, обычно с разрешением в одну секунду. Git будет продолжать считать, что версия индекса соответствует версии рабочего дерева до тех пор, пока ОС не коснется метки времени в версии файла рабочего дерева. Это верно даже в том случае, если вы меняете набор фильтров и/или применяемые преобразования конца строки. Git не понимает, что вы изменили способ работы окончания строки или изменили «чистый ", чтобы сделать что-то другое: он просто видит, что аспект "кеша" индекса говорит: "Я сопоставляю метку времени версии рабочего дерева T". Пока отметка времени версии рабочего дерева все еще T, файл должен быть "чистым".
Следовательно, чтобы обновить эти вещи после изменения любых настроек преобразования текста, вам нужно заставить Git понять, что файл не является чистым. Вы можете touch <path>
установить новую отметку времени «сейчас», которая не будет соответствовать старой отметке времени в индексе. Теперь git add -a
(или что-то еще) будет сканировать как обычно, но, поскольку временные метки не совпадают, на этот раз он найдет файл и повторно отфильтрует его, чтобы добавить в индекс.
Опять же, эти преобразования происходят, когда вы git add
файл.
Обычно в системе, подобной Windows, ваша цель здесь будет состоять в том, чтобы взять файлы формата репозитория только для LF и превратить их в файлы CR-LF для работы с Windows. Это преобразование происходит на пути из индекса, к рабочему дереву: т. е. во время git checkout
. Затем вы захотите преобразовать эти файлы рабочего дерева CR-LF в формат только LF во время процесса git add
, чтобы форма в репозитории была такой, какой их предпочитает Linux (и Линус Торвальдс, и, следовательно, Git :-) ). Но вы можете хранить их внутри репозитория в формате CR-LF, если вы действительно хотите раздражать всех пользователей Unix/Linux. Все дело в том, какие преобразования, если таковые имеются, вы применяете на каких шагах: git checkout
время и git add
время.
Файл .gitattributes
указывает, какие преобразования к каким файлам применять. Настройки core.autocrlf
и core.eol
нет: Git должен сделать все возможное, чтобы определить, какие файлы на каком этапе получают какие преобразования.
1Технически все, что содержится в индексе, — это хэш-идентификатор файла. Сам файл хранится как объект Git blob в базе данных репозитория. Как и в случае с объектами фиксации, эти объекты больших двоичных объектов являются неизменяемыми. Вот почему его нельзя изменить в индексе: на самом деле это просто хэш-идентификатор.
2Процесс git add
просто записывает новый большой двоичный объект, причем новый большой двоичный объект записывается после любой фильтрации. Если новый большой двоичный объект точно соответствует некоторому существующему большому двоичному объекту побитно, новый большой двоичный объект повторно использует существующую запись базы данных большого двоичного объекта и хэш-идентификатор и фактически не сохраняется — существующего большого двоичного объекта достаточно. Если нет, данные большого двоичного объекта сохраняются в виде нового файла с новым идентификатором. Это новый идентификатор хэша, который входит в индекс.
person
torek
schedule
20.02.2017
core.eol
иcore.autocrlf
довольно подробно. - person Sascha Wolf   schedule 20.02.2017