10.4. Packfiles
Это типа конспект, который я веду для себя, чтобы получше разобраться и запомнить. Вероятно, вам лучше сразу читать оригинал: 10.4 Packfiles.
Packfiles
Добавим большой файл big.txt, который весит 20K
И сделаем коммит.
У нас три объекта:
$ find .git/objects -type f -exec ls -l {} \; | awk '{print $5 "\t" $9}'
107 .git/objects/95/27bde652eacdbdf8ad83df98c1e9bf985d9f89
52 .git/objects/f4/54120ed8f5dfae6ecad325c29ca9a185bf296b
8133 .git/objects/48/809b5dea28ec734ea7d0652a094c4fcf49d0b1
Они сжаты, поэтому большой весит всего 8К. Посмотрим его несжатый размер:
$ git cat-file -s 48809b5dea28ec734ea7d0652a094c4fcf49d0b1 19772
Изменим маленько и снова закоммитим. Появилось ещё три объекта: новый блоб, новое дерево и новый коммит. Также заметим, что второй блоб такой же большой, как и первый:
$ find .git/objects -type f -exec ls -l {} \; | awk '{print $5 "\t" $9}'
107 .git/objects/95/27bde652eacdbdf8ad83df98c1e9bf985d9f89
52 .git/objects/69/4d9964132d27e0c43ab23ed7f54188865be620
52 .git/objects/f4/54120ed8f5dfae6ecad325c29ca9a185bf296b
8142 .git/objects/2a/cfd7dad001eb5a180b6c72d6777db67f1e09d2
8133 .git/objects/48/809b5dea28ec734ea7d0652a094c4fcf49d0b1
147 .git/objects/49/a75e550cf189c18c1e2ae427800e76ad6f18d6
Теперь вызовем GC:
$ git gc
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
Что стало с нашими объектами:
7294 .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.pack
1240 .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.idx
1232 .git/objects/info/commit-graph
54 .git/objects/info/packs
У меня не осталось обычных объектов. Остались бы только те, которые не помечены никаким коммитом (dangling — висящие), но у меня таких не было.
Получились файлы Pack, Index и Graph. Получившиеся файлы тоже сжатые, поэтому простым cat файлом их не прочитать. Но у гита есть для этого команды. Прочитаем индекс:
$ git verify-pack -v .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.idx
49a75e550cf189c18c1e2ae427800e76ad6f18d6 commit 183 142 12
9527bde652eacdbdf8ad83df98c1e9bf985d9f89 commit 129 101 154
2acfd7dad001eb5a180b6c72d6777db67f1e09d2 blob 19782 6907 255
694d9964132d27e0c43ab23ed7f54188865be620 tree 35 46 7162
f454120ed8f5dfae6ecad325c29ca9a185bf296b tree 35 46 7208
48809b5dea28ec734ea7d0652a094c4fcf49d0b1 blob 9 20 7254 1 2acfd7dad001eb5a180b6c72d6777db67f1e09d2
non delta: 5 objects
chain length = 1: 1 object
.git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.pack: ok
Видим айдишники шести объектов, их тип. Глазами вижу, что третий столбик похож на размер несжатого содержимого. Четвёртый — неужели сжатый размер?
Пятый — похоже на оффсет, смотрите:
- первый начинается с
12и плюс142байта содержимого; - получается, что следующий это
12 + 142 = 154и плюс101байт сжатого содержимого; - это даёт, что третий начнётся с
154 + 101 = 255.
Внизу три строчки какой-то ещё информации.
Посмотрим на двух наших жирдяев, первого 48809 и второго 2acfd.
Оказалось, что жирдяем остался только второй 2acfd, а первый 48809 усох до 9 несжатых байт.
Мануал объясняет это тем, что на практике нам скорее понадобится последняя версия, а предыдущая нужна реже, поэтому её Git будет вычислять, применяя диффы.
Что интересно, без разницы, какую из этих трёх команд вызывать:
git verify-pack -v .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.idx
git verify-pack -v .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6.pack
git verify-pack -v .git/objects/pack/pack-1b98b811226c5f878f5c180ac15f7aa8aa3af4e6