Skip to content

Commit 9771bfb

Browse files
brabojclaude
andauthored
docs: add packfiles section to Expert Topics (#193)
Covers loose objects vs packfiles, delta compression, git gc/repack, .idx index files, network transfer, and inspection commands. Closes #166 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a9d1fae commit 9771bfb

1 file changed

Lines changed: 104 additions & 0 deletions

File tree

chapters/06-expert-topics.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ In this chapter you will learn:
2222
- How to find the commit that introduced a bug using bisect
2323
- How to automate tasks with Git hooks
2424
- How garbage collection and the reflog protect and clean up orphaned commits
25+
- How packfiles compress objects for efficient storage and network transfer
2526

2627
## 2. Configuration
2728

@@ -417,6 +418,109 @@ $ git branch recovered abc1234 # create a branch pointing to it
417418
Once a branch points to the commit again, it is no longer orphaned and
418419
will not be removed by garbage collection.
419420

421+
## 10. Packfiles
422+
423+
When you create a commit, Git stores each new blob, tree, and commit
424+
as a separate file in `.git/objects/`. These are called **loose
425+
objects** — one file per object, individually compressed with zlib.
426+
This works well for small repositories, but as history grows, thousands
427+
of small files waste disk space and slow down operations.
428+
429+
Git solves this with **packfiles** — a single binary file that bundles
430+
many objects together using delta compression.
431+
432+
### Loose objects vs packfiles
433+
434+
```text
435+
# Loose objects — one file per object
436+
.git/objects/
437+
├── 3b/18e512dba79e... # blob
438+
├── 5f/a3c201af34d2... # tree
439+
├── a1/b2c3d4e5f678... # commit
440+
└── ... # thousands more
441+
```
442+
443+
```text
444+
# After packing — two files replace thousands
445+
.git/objects/pack/
446+
├── pack-abc123.pack # all objects, delta-compressed
447+
└── pack-abc123.idx # index for fast lookup
448+
```
449+
450+
A `.pack` file contains the compressed object data. The `.idx` file
451+
is an index that maps each object hash to its offset inside the pack,
452+
so Git can find any object without scanning the entire file.
453+
454+
### Delta compression
455+
456+
Packfiles do not just concatenate objects — they use **delta
457+
compression**. When two objects are similar (for example, two versions
458+
of the same file), Git stores one in full and the other as a set of
459+
differences (a delta) relative to the first. This is especially
460+
effective for files that change incrementally across commits.
461+
462+
```text
463+
$ git verify-pack -v .git/objects/pack/pack-abc123.idx
464+
a1b2c3d4 blob 1200 450 120
465+
f6e7d8c9 blob 80 65 570 1 a1b2c3d4
466+
```
467+
468+
In this example, `f6e7d8c9` is stored as a delta against `a1b2c3d4`.
469+
Its original size is 80 bytes, but it takes only 65 bytes in the pack
470+
because Git stores just the differences.
471+
472+
### When does packing happen?
473+
474+
Git packs objects automatically during garbage collection:
475+
476+
```text
477+
$ git gc # packs loose objects, removes unreachable ones
478+
$ git repack -a -d # repack all objects, delete old packs
479+
```
480+
481+
Packing also happens automatically when:
482+
483+
- The number of loose objects exceeds `gc.auto` (default: 6700)
484+
- You run `git push` or `git fetch` — Git builds a packfile
485+
specifically for network transfer
486+
487+
### Packfiles and network transfer
488+
489+
When you push or fetch, Git does not send loose objects one at a time.
490+
It builds a **thin packfile** — a temporary pack that contains only
491+
the objects the other side is missing, delta-compressed against objects
492+
both sides already have. This makes network operations fast even for
493+
large repositories.
494+
495+
```text
496+
$ git push origin main
497+
Enumerating objects: 5, done.
498+
Counting objects: 100% (5/5), done.
499+
Delta compression using up to 8 threads
500+
Compressing objects: 100% (3/3), done.
501+
Writing objects: 100% (3/3), 320 bytes | 320.00 KiB/s, done.
502+
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
503+
```
504+
505+
The "Delta compression" and "Compressing objects" lines show Git
506+
building the packfile for transfer.
507+
508+
### Inspecting packfiles
509+
510+
```text
511+
# List all packs
512+
$ ls .git/objects/pack/
513+
514+
# Show pack contents with sizes and deltas
515+
$ git verify-pack -v .git/objects/pack/pack-abc123.idx
516+
517+
# Count loose vs packed objects
518+
$ git count-objects -v
519+
count: 12 # loose objects
520+
packs: 1 # number of packfiles
521+
size-pack: 4820 # total packed size in KiB
522+
```
523+
420524
## Exercises
421525

422526
All exercises use the `concepts-lab` repository from previous chapters.

0 commit comments

Comments
 (0)