Как Git экономить место и быстро в одно и то же время?

Я только что увидел первый Git учебник http://blip.tv/play/Aeu2CAI.

Как Git хранит все версии всех файлов и как он может быть более экономичным в пространстве, чем Subversion который сохраняет только последнюю версию кода?

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

Итак, я предполагаю, что

  • Git сжимает данные экстенсивно
  • Это еще быстрее, потому что uncompression + work все еще быстрее, чем network_fetch + work

Правильно ли я? Даже близко?

Ответ 1

Я предполагаю, что вы спрашиваете, как возможно, чтобы клон git (полный репозиторий + checkout) был меньше, чем извлеченные источники в Subversion. Или вы имели в виду что-то еще?

Этот вопрос отвечает в комментариях


Размер репозитория

Сначала вы должны принять во внимание, что после проверки (рабочая версия) Subversion хранит чистую копию (последняя версия) в тех подкаталогах .svn. Принудительная копия хранится несжатым в Subversion.

Во-вторых, git использует следующие методы, чтобы сделать репозиторий меньшим:

  • каждая версия файла сохраняется только один раз; это означает, что если у вас есть только две разные версии некоторого файла в 10 версиях (10 коммитов), git хранит только эти две версии, а не 10.
  • объекты (и дельта, см. ниже) хранятся сжатыми; текстовые файлы, используемые в программировании, очень хорошо сжимаются (около 60% от исходного размера или 40% уменьшения размера от сжатия).
  • после переупаковки объекты хранятся в дефинированной форме, в отличие от другой версии; дополнительно git пытается упорядочить дельта-цепи таким образом, что дельта состоит в основном из делеций (в обычном случае растущих файлов она находится в порядке повторения); Дельта IIRC также сжимаются.

Производительность (скорость работы)

Во-первых, любая операция, которая связана с сетью, будет намного медленнее локальной операции. Поэтому, например, сравнение текущего состояния рабочей области с какой-либо другой версией или получение журнала (истории), который в Subversion включает в себя сетевое подключение и сетевую передачу, а в git - локальная операция, конечно, будет намного медленнее в Subversion, чем в Git. КСТАТИ. это разница между системами управления версиями централизованного (с использованием клиент-серверного рабочего процесса) и распределенных систем управления версиями (с использованием однорангового рабочего процесса), причем не только между Subversion и Git.

Во-вторых, если я правильно понимаю, в настоящее время ограничение - это не процессор, а IO (доступ к диску). Поэтому возможно, что выигрыш от необходимости считывать меньше данных с диска из-за сжатия (и иметь возможность копировать его в память) преодолевает потерю от необходимости декомпрессии данных.

В-третьих, git был разработан с учетом производительности (см., например, GitHistory на git Wiki):

  • В индексе хранится информация о статистике для файлов, а git использует его для определения без проверки файлов, если файлы были изменены или нет (см., например, core.trustctime config).
  • Максимальная глубина дельты ограничена pack.depth, которая по умолчанию равна 50. git имеет дельта-кеш для ускорения доступа. Существует файл (сгенерированный) packfile для быстрого доступа к объектам в файле pack.
  • Git заботится о том, чтобы не прикасаться к файлам, которые ему не нужны. Например, при переключении ветвей или перемотке на другую версию, git обновляет только те файлы, которые были изменены. Следствием этой философии является то, что git поддерживает только очень минимальное расширение ключевого слова (по крайней мере, из коробки).
  • Git использует собственная версия LibXDiff, в настоящее время также для diff и merge, вместо вызова внешнего инструмента diff/external merge.
  • Git пытается минимизировать латентность, что означает хорошую воспринимаемую производительность. Например, он выводит первую страницу "git log" как можно быстрее, и вы видите ее почти сразу, даже если генерация полной истории займет больше времени; он не дожидается полной генерации истории перед ее отображением.
  • При извлечении новых изменений git проверяет, какие объекты у вас общие с сервером, и отправляет только (сжатые) различия в виде тонкого пакетного файла. По общему признанию, Subversion может (или, возможно, по умолчанию она) также отправлять только различия при обновлении.

Я не хакер git, и я, вероятно, пропустил некоторые приемы и трюки, которые git использует для лучшей производительности. Однако обратите внимание, что git сильно использует POSIX (например, файлы с отображением памяти), поэтому усиление может быть не таким большим в MS Windows.

Ответ 2

Не полный ответ, но те комментарии (от AlBlue) может помочь в аспекте управления пространством вопроса:

Здесь кое-что нужно разъяснить.

Во-первых, возможно иметь более крупный репозиторий Git, чем репозиторий SVN; Надеюсь, я не подразумевал, что это никогда не было так. Однако на практике обычно имеет место, что репозиторий Git занимает меньше места на диске, чем эквивалентный репозиторий SVN.
Одна вещь, которую вы цитируете, - это репозиторий SVN с одиночным SVN, который, очевидно, массивный. Однако нужно смотреть только на git.apache.org, и вы заметите, что каждый проект Apache имеет свой собственный репозиторий Git. То, что действительно необходимо, - это сравнение похожих друг на друга; другими словами, проверка проекта (abdera) SVN против клона репозитория (abdera) Git.

Мне удалось проверить git://git.apache.org/abdera.git. На диске он потребляет 28.8Mb.
Затем я проверил версию SVN http://svn.apache.org/repos/asf/abdera/java/trunk/, и он потреблял 34.3Mb.
Оба номера были взяты из отдельно смонтированного раздела в пространстве оперативной памяти, а число, указанное в цикле, было числом байтов, взятых с диска.
Если использовать du -sh как средство тестирования, проверка Git составляла 11 Мб, а проверка SVN составляла 17 МБ.

Версия Apache Abdera Git позволит мне работать с любой версией истории вплоть до текущей версии; SVN будет иметь только резервную копию текущей версии. Тем не менее это занимает меньше места на диске.

Как вы можете спросить?

Ну, для чего-то, SVN создает намного больше файлов. Вывод SVN имеет 2959 файлов; в соответствующем репозитории Git содержится 845 файлов.

Во-вторых, , в то время как SVN имеет папку .svn на каждом уровне иерархии, репо Git имеет только один репозиторий .git на верхнем уровне. Это означает (между прочим), что переименование из одного каталога в другой имеет относительно меньшее влияние в Git, чем в SVN, что, в свою очередь, уже имеет относительно небольшой эффект.

В-третьих, Git сохраняет свои данные как сжатые объекты, тогда как SVN сохраняет их как несжатые копии. Перейдите в любой каталог .svn/text-base, и вы найдете несжатые копии (базовых) файлов.
Git имеет механизм сжатия всех файлов (и, действительно, всей истории) в файлы пакетов. В случае с Abdera .git/objects/pack/ имеет один файл .pack(содержащий всю историю) в файле 4.8Mb.
Таким образом, размер репозитория (примерно) такого же размера, как и текущий проверочный код, в этом случае я бы не ожидал, что это всегда так.

В любом случае, вы правы, что история может расти больше, чем общий размер текущей проверки; но из-за того, что SVN работает, он действительно должен приближаться вдвое больше, чтобы сделать большую часть разницы. Даже тогда сокращение дискового пространства на самом деле не является основной причиной использования DVCS; это преимущество для некоторых вещей, конечно, но это не настоящая причина, почему люди используют его.

Обратите внимание, что Git (и Hg и другие DVCS) действительно страдают от проблемы, когда (большие) двоичные файлы проверяются, а затем удаляются, поскольку они все равно будут отображаться в репозитории и занимать место, даже если они не текущие. Сжатие текста позаботится об этих вещах для текстовых файлов, но двоичные - это большая проблема. (Существуют административные команды, которые могут обновлять содержимое репозиториев Git, но они имеют несколько более высокую накладную/административную стоимость, чем CVS; Git ветвь фильтра похожа на svnadmin dump/filter/load.)


Что касается аспекта скорости, я упомянул об этом в своем "как быстро Git по подрывной работе с удаленными операциями?" ответ (например Линус сказал в своей презентации Google: (перефразируя здесь) "все, что связано с сетью, просто убьет выступления" )

И документ GitBenchmark, упомянутый Jakub Narębski, является хорошим дополнением, хотя он не имеет прямого отношения к Subversion.
Он перечисляет тип операции, которую необходимо отслеживать по показателю DVCS.

Другие Git критерии упоминаются в этом SO-вопросе.