[newbies] Q: Git (repack, gc, fsck)

Ivan A. Melnikov iv на altlinux.org
Вс Авг 1 07:35:44 UTC 2010


В Sat, 31 Jul 2010 23:16:24 +0700
Slava Semushin <slava.semushin на gmail.com> пишет:

> Здравствуйте!

Здравствуйте.

> К сожалению, не очень представляю себе как работают, что делают и чем
> полезны команды git -- repack, gc и fsck. [...]

Расскажу, как я это понимаю.

== Немного теории ==

Как известно, git внутри хранит данные в виде объектов нескольких типов
(blob, tree, commit, tag). Изначально эти объекты хранятся в файлах,
названных по SHA-сумме этого объекта, внутри .git/objects. Для большей
эффективности несколько объектов могут быть объединены в один pack. Там,
помимо обычного сжатия, используется delta-compression, для
эффективного хранения одинаковых или мало отличающихся кусков различных
объектов (даже логически не связанных), поэтому хорошо перепаковав
репозиторий можно сэкономить много дискового пространства.

Интересующихся подробностями используемых алгоритмов всё-таки отошлю,
например, к git.git/Documentation/technical/pack-heuristics.txt -- 18
килобайт английских букв, манера изложения забавна, даже перевести
захотелось.

== git repack ==

Его задача, как прямо указывает man, объединять объекты в pack'и, а
также объединять несколько pack'ов в один. Что хорошо, выполнять его
можно довольно смело, он не теряет информацию. Что плохо, при
неаккуратном использовании размер репозитория может даже возрасти.

Пример аккуратного использования:

$ du -s .
940K	.
$ git repack
Counting objects: 76, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (62/62), done.
Writing objects: 100% (76/76), done.
Total 76 (delta 37), reused 0 (delta 0)
$ du -s .
964K	.
$ git prune-packed
$ du -s .
400K	.

git prune-packed удалил из .git/objects те объекты, которые присутствуют
в запакованном виде. То есть, после git repack некоторые объекты
присутствовали как сами по себе, так и внутри pack'а.

Другой удачный пример -- команда
$ git repack -a -d -f --window=200 --depth=200
неоднократно экономила мне много места для таких огромных репозиториев,
как ядро или qt, до того как я узнал про git gc --aggressive.

== git gc ==

Довольно "высокоуровневая" команда, которую рекомендуют запускать
периодически, чтобы не давать репозиторию слишком разрастаться. Помимо
запаковки новых объектов тем же git repack, выполняет несколько
дополнительных действий, например удаляет недоступные (unreachable)
объекты (как сборщики мусора во многих языках программирования).

То есть, если вы часто делатете git rebase --hard, а потом хватаетесь за
голову, используйте git gc с осторожностью. Хотя, по умолчанию, у Вас
всё равно есть 30 дней, чтобы за эту самую голову схватиться:
недоступные commit'ы удаляются не сразу.

В остальных случаях эта команда, вроде бы, ничего страшного делать не
должна.

Ещё есть вариант использования
$ git gc --aggressive
который рекомендуется всем, кто хочет сэкономить место на жестком диске,
но побаивается (как я) тонкостей git repack. It just does the right
thing (чаще всего).

== git fsck ==

Проверяет целостность репозитория. В принципе, никаких изменений не
вносит, но позволяет получить некоторую информацию. В частности, может
показать:

- объекты, которые присутствуют, но нигде напрямую не используются;
- объекты, которые не присутствуют, но используются (имеются ссылки на
  них);
- объекты, sha1-сумма которых не верна (не соответствует имени).

git fsck полезна, например, после того, как Вы схватитесь за голову
после git rebase --hard. По крайней мере, у меня был один такой
случай...

== Disclaimer ==

Ещё раз повторюсь, что это моё понимание, и оно может быть неверным в
некоторых деталях. Или в принципе неверным =). Надеюсь, получилось не
слишком мутно, и я помог больше, чем запутал.

-- 
WBR,
Ivan A. Melnikov


Подробная информация о списке рассылки devel-newbies