Git на самом деле не имеет понятия «незафиксированный файл».У него есть index и work-tree .
. Главное, что хранит Git: commits:
Коммиты - это постоянные (в основном 1 ), полностью доступные только для чтения сущности, хранящиеся в своего рода базе данных (простое хранилище значений ключей , действительно), которыеразрешить Git получить доступ к полному снимку источника, который вы или коммиттер сделали, когда вы или коммиттер сделали этот коммит.Наряду с этим моментальным снимком, вы - я не буду здесь указывать «или коммиттер», но, конечно, это подразумевается, - получите возможность добавить свои собственные метаданные, в частности, сообщение журнала о почему Вы сделали этот коммит.
«Истинное имя» любого коммита - это его хэш-идентификатор.Git использует хэш-идентификатор в качестве ключа в хранилище значений ключей, чтобы получить фиксацию.Каждый коммит также содержит хеш-идентификатор своего предшественника или родительский коммит (или, для коммитов слияния, два или более родительских хеш-идентификатора - это то, что делает их «коммитами слияния»).
Один коммит всегда является текущим коммитом.Это тот коммит, который вы выбрали (через git checkout
) для работы.Поскольку коммиты доступны только для чтения, вы не можете изменить этот коммит.В какой-то момент вы можете сделать новый коммит.Обычно этот новый коммит будет использовать текущий коммит в качестве родителя нового коммита, а затем станет текущим коммитом, и именно поэтому вы всегда можете вернуть каждый файл, который вы когда-либо фиксировали: коммиты являются постоянными (в основном)и только для чтения (полностью) и помните своих родителей.
Файлы, сохраненные с коммитом - сделанным вами снимком - сохраняются в сжатом формате Git-only, который бесполезен ни для чего, кроме Git.Таким образом, эти файлы должны быть извлечены из каждого коммита, прежде чем вы сможете их использовать.Следовательно, Git также имеет:
Рабочее дерево.Здесь Git может извлечь файлы из коммита в формат, в котором их использует компьютер.Эти файлы не должны передаваться между компьютерами не потому, что он не может работать, а потому, что он может, и это просто создает большие головные боли, как вы обнаруживаете.
Поскольку файлы в работе -дерево хранится в собственном формате и используется другими программами. Git предлагает возможность модифицировать файлов - особенно таких, как окончания строк и биты разрешений, - когда они выходят из коммита в пути.в рабочем дереве, и когда они переходят из рабочего дерева в коммит.Но есть еще один ключевой момент, и именно здесь возникают самые большие головные боли.
index .Этот элемент находится между текущего коммита и рабочим деревом.
Индекс хранит все файлы в специальном формате Git-only.Это начинается , содержащее файлы, какими они были, когда они были зафиксированы.Ключевое различие между копией файлов коммита и копией индекса заключается в том, что вы можете изменить тех, что в индексе.Вы изменяете их на , заменяя их оптом , используя git add
, чтобы скопировать файл рабочего дерева обратно в индекс.
Когда вы делаете новый коммит, Gitпросто использует то, что находится в индексе в то время.Все файлы уже есть, все предварительно упакованы в формате Git-only.Это делает фиксацию очень быстрой.
Это также означает, что преобразование из формата Git-only в формат «может использоваться этим компьютером» и наоборот происходит при копировании из индекса в рабочийtree (который изменяет файлы с Git-only на useable) и git add
копировать из рабочего дерева в индекс (который меняет useable на Git-only).
Этопочти всегда самая медленная часть работы с коммитами и файлами, поэтому индекс отслеживает (индексы!) рабочего дерева, используя информацию, специфичную для ОС.Эта специфичная для ОС информация, найденная через ОС о рабочем дереве, попадает в индекс.
Если вы разделяете рабочее дерево и файлы индекса и .git
на разных машинах,происходит то, что сам индекс становится бесполезным, потому что специфичные для ОС данные рабочего дерева хранятся в , индекс предназначен для ВМ или хоста, но никогда для обоих одновременно.
Если индекс верен и правильно описывает рабочее дерево, git status
быстро и точно.Когда это не так, два различий, которые он должен выполнить - см. Мой ответ на вопрос, который вы связали - не могут быть выполнены почти так же эффективно.Если вы используете какие-либо преобразования файлов, их нужно либо повторно запустить, либо предположить, что они изменили файлы.
TL; DR всего этого: Никогда не делиться Gitтаким образом, используйте хранилище для извлечения данных. Это не потому, что он не работает, а потому, что он может работать, но становится ужасным опытом.Выявленные вами проблемы сворачивания имен файлов - это вершина другого целого кошмарного айсберга (не решается напрямую, если не делится хранилищем, но, по крайней мере, возможно , чтобы решить эту проблему).
1 Вы можете удалить коммит, если вы также удалите всех его детей и их детей и так далее.То есть удаление коммита требует своего рода геноцида на линии коммита.Это часто плохая идея, и если вы собираетесь это делать, вам обычно приходится копировать всю цепочку детей, но иногда это хорошая идея, и фактически это то, что git rebase
делает внутри.
Обратите внимание, что git commit --amend
не не меняет коммит.Вместо этого он просто отодвигает (и, таким образом, в конечном итоге убивает и удаляет) существующий коммит в конце цепочки, создавая новый замещающий коммит в конце цепочки, используя в качестве родителя нового коммита родительский элемент текущего коммита.