Сколько дискового пространства занимает git commit - PullRequest
2 голосов
/ 29 июня 2011

По данным этой страницы http://www.eecs.harvard.edu/~cduan/technical/git/git-1.shtml

Объект коммита содержит три вещи:

  • Набор файлов, отражающих состояние проекта в данный момент времени.
  • Ссылки на родительские объекты фиксации.
  • Имя SHA1, строка из 40 символов, которая однозначно идентифицирует коммит объект. Имя состоит из хэша соответствующих аспектов коммита, так идентичные коммиты всегда будут иметь то же имя.

Мой вопрос касается первого пункта: Если мой текущий размер проекта составляет 10 МБ, то добавление нового коммита займет еще 10 МБ? поскольку согласно первому пункту каждый коммит содержит набор файлов, отражающих состояние проекта.

Ответы [ 5 ]

5 голосов
/ 29 июня 2011

Я не уверен, что другие ответы действительно полностью ответили на ваш вопрос.

Git хранит коммиты и фактическое содержимое файла отдельно. Коммит не содержит файлов - он содержит ссылки на хешей файлов, содержащихся в коммите. Файлы хранятся отдельно от коммитов, и если два коммита имеют одинаковую версию файла, оба этих коммита будут ссылаться на один и тот же хеш , но сам файл не дублируется. Если файл изменяется между фиксациями, файл сохраняется дважды, каждая версия файла имеет свой собственный хэш, и фиксации будут ссылаться на разные хеши.

Допустим, вы начинаете с одного коммита, который содержит два файла, a.txt и b.txt, каждый из которых хэширует свое значение:

Commit 1:
Filename    |    Hash
---------------------
a.txt       | abcdef111111
b.txt       | ghijkl222222

Обратите внимание, что коммит не содержит содержимого файла. Git хранит содержимое файлов и хэшей в другом месте.

File store:
Hash         |    File contents
---------------------------------
abcdef111111 | hello world
ghijkl222222 | int main()

Допустим, вы обновили a.txt и сделали новый коммит. Во-первых, Git сохраняет новую версию файла в своем хранилище содержимого файла:

File store:
Hash         |    File contents
---------------------------------
abcdef111111 | hello world
ghijkl222222 | int main()
zyxwvu999999 | goodbye world     <-- new entry

И новый коммит указывает на этот хеш как содержащий содержимое a.txt:

Commit 2:
Filename    |    Hash
---------------------
a.txt       | zyxwvu999999
b.txt       | ghijkl222222

Поскольку b.txt не изменился, его не нужно было снова хранить. Второй коммит просто ссылается на тот же хеш, что и первый коммит.

2 голосов
/ 30 июня 2011

Нет.

В коммит входит дерево объектов, которое снимает исходное дерево, но дерево объектов повторно использует неизмененные объекты из предыдущих снимков.Таким образом, каждый коммит добавляет только объекты для файлов и каталогов с изменениями, он не хранит все состояние целиком.

Вдобавок к этому , Git также будет периодически упаковывать свободные объекты в «packfiles”, Которые хранят содержимое многих файлов одновременно, но в которых файлы могут ссылаться на части друг друга (примерно).Это может быть чрезвычайно эффективно при устранении избыточности.

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

В качестве крайнего примера, у меня есть репозиторий, в который я фиксирую дампы SQL из производственной базы данных.В настоящее время размер файла дампа SQL составляет 56 МБ.Каталог .git, содержащий 377 коммитов (т. Е. Резервные копии за 1 год), составляет всего 32 МБ .(Сжатие этого файла с помощью xz -Mmax -9 сокращает его до 2,4 МБ, но с 370 такими файлами, которые все еще близки к 1 ГБ / год.) Поэтому я использую Git как очень удобный тип сжатого архива.

2 голосов
/ 29 июня 2011

Нет. Коммит Git содержит только ссылки на дерево, родительские SHA (которые содержат историю) и другую информацию, такую ​​как автор, комментарии, метка времени и т. Д. Фактические изменения не сохраняются в коммите. Хорошее описание дано на этой странице и в той же статье:

Обратите внимание, что коммит сам по себе не содержит никакой информации о том, что действительно изменилось; все изменения рассчитываются путем сравнения содержимого дерева, на которое ссылается этот коммит, с деревьями, связанными с его родителями.

В SVN и связанных с ним vcs они хранят две копии одного и того же файла, одну в рабочем каталоге и одну в .svn/, которая используется для сравнения и фиксации. В результате в больших проектах размер репо значительно увеличивается с фиксацией. Например, весь репозиторий проекта Mozilla составляет около 12 ГБ с использованием SVN, тогда как то же самое составляет только около 420 МБ с git [1]

1 голос
/ 29 июня 2011

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

Когда изменяется содержимое файла, скажем, новое содержимое добавляется к объектам и дерево обновляетсяна этот новый контент для файла, и фиксация будет указывать на это новое древовидное состояние.

Выполните git cat-file commit HEAD, и вы сможете получить некоторое представление о том, что на самом деле имеет фиксация.

Кроме того,посмотрите на Git from bottom up (бесплатно) или на книгу Version Control with Git, у обоих есть хорошее объяснение о понятиях BLOB, деревьев и коммитов.

0 голосов
/ 29 июня 2011

Сохраняется только delta между коммитами. Все известные мне СКМ о дельтах магазинов. Однако случай может отличаться, если рассматриваемые файлы содержат двоичные данные. Тогда дельта может быть невозможна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...