Как git хранить файлы?

Я только начал изучать git, и для этого начал читать git Community Book, и в этой книге они говорят, что SVN и CVS сохраняют разницу между файлами и что git хранит моментальный снимок всех файлов.

Но я действительно не понял то, что они подразумевают под снимком. Действительно ли git делает копию всех файлов в каждой фиксации, потому что это то, что я понял из их объяснения.

PS: Если у кого-то есть лучший источник для изучения git, я был бы признателен.

Ответ 1

Git включает для каждого коммита полную копию всех файлов, за исключением того, что для контента, уже присутствующего в репозитории Git, снимок будет просто указывать на указанный контент, а не дублировать его.
Это также означает, что несколько файлов с одинаковым содержимым хранятся только один раз.

Таким образом, снимок - это в основном коммит, ссылающийся на содержимое структуры каталогов.

Некоторые хорошие ссылки:

Вы говорите Git, что хотите сохранить снимок вашего проекта с помощью команды git commit, и он в основном записывает манифест того, как все файлы в вашем проекте выглядят в этот момент.

Лабораторная работа 12 иллюстрирует, как получить предыдущие снимки


Книга Progit содержит более полное описание снимка:

Основное различие между Git и любой другой VCS (включая Subversion и друзей) заключается в том, как Git думает о своих данных.
Концептуально большинство других систем хранят информацию в виде списка изменений на основе файлов. Эти системы (CVS, Subversion, Perforce, Bazaar и т.д.) Воспринимают информацию, которую они хранят, как набор файлов и изменения, вносимые в каждый файл с течением времени.

delta-based VCS

Git не думает и не хранит свои данные таким образом. Вместо этого Git думает о своих данных больше как набор снимков мини файловой системы.
Каждый раз, когда вы фиксируете или сохраняете состояние вашего проекта в Git, он в основном делает снимок того, как все ваши файлы выглядят в данный момент, и сохраняет ссылку на этот снимок.
Чтобы быть эффективными, если файлы не изменились, Git не сохраняет файл снова - просто ссылка на предыдущий идентичный файл, который он уже сохранил.
Git думает о своих данных, как показано ниже:

snapshot-based VCS

Это важное различие между Git и почти всеми другими VCS. Это заставляет Git пересматривать практически все аспекты контроля версий, которые большинство других систем скопировали из предыдущего поколения. Это делает Git больше похожим на мини файловую систему с несколькими невероятно мощными инструментами, построенными на ее основе, а не просто на VCS.


Ян Худек добавляет этот важный комментарий:

Хотя это верно и важно на концептуальном уровне, это НЕ верно на уровне хранилища.
Git использует дельты для хранения.
Не только это, но это более эффективно в этом, чем любая другая система. Поскольку он не хранит историю для каждого файла, когда он хочет выполнить дельта-сжатие, он берет каждый BLOB-объект, выбирает некоторые BLOB-объекты, которые могут быть похожими (используя эвристику, которая включает в себя самое близкое приближение предыдущей версии и некоторые другие), пытается генерировать дельты и выбирает самые маленькие. Таким образом, он может (часто зависит от эвристики) использовать преимущества других похожих файлов или более старых версий, которые более похожи на предыдущие. Параметр "окно пакета" позволяет торговать производительность для качества дельта-сжатия. Значение по умолчанию (10) обычно дает приличные результаты, но когда пространство ограничено или для ускорения передачи по сети, git gc --aggressive использует значение 250, что делает его работу очень медленной, но обеспечивает дополнительное сжатие для данных истории.

Ответ 2

Git логически сохраняет каждый файл под своим SHA1. Это означает, что если у вас есть два файла с одинаковым содержимым в хранилище (или если вы переименуете файл), сохраняется только одна копия.

Но это также означает, что когда вы изменяете небольшую часть файла и фиксируете, сохраняется другая копия файла. Git решает эту проблему, используя файлы пакета. Время от времени все "свободные" файлы (на самом деле, не только файлы, но и объекты, содержащие информацию о коммитах и каталогах) из репозитория собираются и сжимаются в пакетный файл. Файл пакета сжимается с помощью zlib. И подобные файлы также дельта-сжаты.

Этот же формат также используется при извлечении или отправке (по крайней мере, с некоторыми протоколами), поэтому эти файлы не нужно повторно сжимать.

Результатом этого является то, что репозиторий git, содержащий всю несжатую рабочую копию, несжатые последние файлы и сжатые старые файлы, как правило, относительно мал, в два раза меньше, чем размер рабочей копии. А это означает, что он меньше, чем репозиторий SVN с теми же файлами, хотя SVN не хранит историю локально.

Ответ 3

Да, git делает копию файлов. Философия заключается в том, что в большинстве случаев дисковое пространство по существу является бесплатным в больших количествах.

Вот почему большие ресурсы (видео, звуковые записи и т.д.) часто не отслеживаются при использовании git. См., Например, эту дискуссию.

P.S. Там хорошее введение Ларса Фогеля в git здесь.

Ответ 4

Ответы выше довольно хороши, но я хотел бы добавить еще одну маленькую крошечную концепцию, известную как дельта-кодирование. Эффективность сохраняется до тех пор, пока не будет записан файл пакета. Свободные объекты записываются в сжатом, но не дельта-формате во время каждой фиксации.