Вы должны быть здесь осторожны, потому что Git имеет некоторые встроенные преобразования, и они сильно предпочитают окончания строк только для LF . Если вы используете встроенные преобразования, это то, что вы действительно получите в своем хранилище . Но мы должны различать guish между тем, что находится в хранилище , и тем, что находится в вашем рабочем дереве .
Вы не работаете с файлами в хранилище потому что они не подходят для работы. Вы работаете с файлами в вашем рабочем дереве. И, в некотором смысле, Git даже не хранит файлы , потому что базовая c единица хранения Git - это commit . Но коммиты сами хранят (снимки) файлов, поэтому в этом смысле Git хранит файлы. Просто они все коммитили, или их нет, одновременно.
Файлы внутри каждого коммита Git хранятся в специальном, только для чтения, Git -только сжатая форма. Другие программы на вашем компьютере, включая ваши редакторы и средства просмотра файлов, не могут работать с этими файлами. 1 Они отлично подходят для архивирования и совершенно бесполезны, по крайней мере сами по себе, для получения любых новая работа выполнена.
Итак, когда вы используете git checkout
для выбора конкретного коммита, Git извлекает этих файлов. Они выходят из коммита, переходя от специального, только для чтения, Git -только, сублимированного формата, к обычным обычным файлам. Эти несжатые и восстановленные файлы могут использоваться каждой программой на вашем компьютере. Это те файлы, которые вы увидите и с которыми будете работать, и Git копирует их в ваше рабочее дерево: область, в которой вы выполняете свою работу.
Рабочее дерево не является действительно часть хранилища. И когда Git изменяет формат файла в соответствии с .gitattributes
или core.autocrlf
или любым из этих других параметров, которые вы можете выбрать, Git только делает их при копировании файлов из индекса в рабочее дерево и при копировании файлов из рабочего дерева в индекс. Мы еще не коснулись индекса, но пришло время сделать это.
1 Некоторые редакторы, вероятно, могут , на данный момент: I ' я был бы удивлен, если бы не было режима GNU-emacs для просмотра, например, Git внутренних объектов. :-) Но большинство вообще не может, и в любом случае не нужно.
Индекс находится между коммитами и рабочим деревом
Индекс, возможно, лучше всего описать в одной фразе как место, где вы строите свой следующий коммит . Эта вещь, которая Git по-разному вызывает index , область подготовки или (редко в наши дни) кеш , на самом деле имеет несколько функций. В частности, это очень важно при работе с конфликтующим слиянием. Но для наших целей мы заботимся только о том, чтобы он находился между зафиксированными файлами и копиями рабочих файлов этих файлов. 2
То есть: когда вы спрашиваете Git чтобы проверить конкретный коммит, Git делает копирование 3 файлов, которые хранятся в этом коммите, в индекс. В отличие от замороженных файлов в коммитах, копии в индексе могут быть перезаписаны. Затем, скопировав коммит в индекс, Git теперь копирует файлы индекса в рабочее дерево.
Этот последний шаг - копирование файла индекса в рабочее дерево - это когда Git завершает работу. офлайн преобразования. Существует только одно преобразование Git может сделать здесь самостоятельно: оно может превратить строки с новой строкой в строки с CRLF.
Теперь, когда все ваши файлы находятся в вашем рабочем дереве, Вы можете работать над ними сколько угодно. Вы можете оставить окончания строк одинаковыми или изменить их по своему усмотрению. Вы можете заменить файлы оптом или отредактировать их редакторами или чем угодно. Это просто файлы , и они полностью находятся под вашим контролем.
Теперь, когда вы изменили этих файлов, тем не менее, вы можете захотеть, чтобы ваши были следующими подтвердите наличие обновленных файлов. Здесь вы должны запустить git add
: git add
скопирует файл рабочего дерева в индекс. Это сжимает и, в противном случае, Git - определяет файл, так что теперь он находится в сублимированном формате в индексе и готов к фиксации. 4 И, опять же, здесь есть только одно преобразование, встроенное в Git: может заменить окончания строк CRLF окончаниями строк только для новой строки.
Git не может изменить на окончания CRLF в хранилище
Обратите внимание на два преобразования, встроенные в Git. Все настроек управления, будь то .gitattributes
или нет, просто включают или выключают эти настройки преобразования. Либо Git превращает новые строки в CRLF при выходе из индекса в рабочее дерево, либо нет. Либо Git превращает CRLF в новые строки при переходе с рабочего дерева на индекс, либо нет. Не существует процесса, с помощью которого Git может превращать окончания строки в CRLF-окончания в индексе.
Конечно, вы можете просто не использовать преобразования, встроенные в Git. Но если вы хотите работать с CRLF-окончаниями, и все же store - в репозитории - только для новых строк, вы можете организовать это. Реальные вопросы здесь:
- Вас волнует, что находится в хранилище , внутри коммитов или только что в рабочем дереве ?
- Если вас волнует, что находится в хранилище, что вы хотите в хранилище внутри коммитов?
- Если одобренные Git окончания только для новой строки допустимы в хранилище, пока вы получаете окончания CRLF в рабочем дереве, готовы ли вы заплатить небольшую цену за выполнение этих преобразований?
Если ответ на последний вопрос заключается в том, что они приемлемы и да, тогда забудьте о том, что находится в хранилище , и сконцентрируйтесь на правильной настройке в .gitattributes
. Git выполнит необходимые преобразования во время операций извлечения файлов и операций git add
.
Если ответ на второй вопрос заключается в том, что вас волнует, что находится в хранилище , и вам нужны окончания CRLF, вы, вероятно, не должны использовать встроенные преобразования Git. Вы можете написать свои собственные фильтры smudge и clean , чтобы делать то, что вы хотите: создать «чистые» строки хранилища фильтров с окончаниями CRLF. (Тот факт, что для этого нет встроенных методов, означает, что, если вы считаете, что хотите этого, вы должны быть совершенно уверены: Git люди стараются достаточно хорошо охватить Windows и MacOS.)
2 В некотором смысле, индекс не требуется . Другие системы контроля версий работают нормально без них. Но здесь, мы должны знать об этом, потому что именно так все это работает на самом деле, в Git.
3 Git фактически не копирует их. Из-за их обезвоженной / лиофилизированной формы, Git может просто ссылаться на зафиксированных файлов. На самом деле в индексе есть Git внутренний объект BLOB га sh идентификаторы, плюс имя каждого файла, а также множество make-it- go -fast кеш данных все устроено так, что подходит для Git и не подходит ни для чего другого. Но если вы не начнете просматривать части индекса, например, с git ls-files --stage
или git update-index
, все это на самом деле не имеет значения. Вы можете думать о том, что в индексе, как о копиях файлов, и все это работает.
4 Технически, git add
создает новый объект blob , или повторно использует некоторый существующий объект BLOB-объекта, если таковой имеется с правильным содержимым. Затем он помещает блоб ha sh в указатель, как отмечено в сноске 3. Но опять же вы можете просто думать об этом как об операции копирования: он работает так же.