GitRepacking (git repack)

git repack

Git stores objects in two ways: as individual loose files under .git/objects/, or inside compressed pack files (.pack) in .git/objects/pack/. git repack consolidates loose objects and existing pack files into new, optimized pack files using delta compression. The result is a much smaller repository that performs better for clones and fetches. Most of the time, git gc calls git repack for you — but understanding repack directly helps you tune repository performance.

How Delta Compression Works

When Git packs objects, it does not simply compress each one independently. Instead, it finds objects that are similar to each other (for example, different versions of the same file) and stores most of them as deltas — just the differences from a base object. A file that changes by 10 lines across 100 commits might be stored as one full copy plus 99 tiny delta objects, rather than 100 full copies. This is what makes pack files dramatically smaller than storing objects individually.

Before repack — loose objects

Text
.git/objects/
  4b/825dc642cb6eb9a060e54bf8d69288fbee4904  ← each object is a separate file
  9d/aeafb9864cf43055ae93beb0afd6c7d144bfa4
  e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
  ... (thousands more files)

After repack — pack files

Text
.git/objects/pack/
  pack-a1b2c3d4e5f6789012345678901234567890.idx   ← index for fast object lookup
  pack-a1b2c3d4e5f6789012345678901234567890.pack  ← all objects delta-compressed
git repack -a: Pack All Objects

The -a flag packs all reachable objects (including those already in existing pack files) into a single new pack file. This creates one authoritative pack but does NOT delete the old pack files — use -d for that.

Pack all objects into one new pack

Bash
git repack -a
git repack -A -d: Pack All and Delete Redundant Packs

The combination -A -d is the most commonly used form. -A unpacks objects from existing packs before repacking (unlike lowercase -a which just packs everything together), and -d deletes redundant pack files afterward — packs whose contents are now fully contained in the new pack.

Full repack with cleanup

Bash
git repack -A -d

Example output

Text
Enumerating objects: 8241, done.
Counting objects: 100% (8241/8241), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4118/4118), done.
Writing objects: 100% (8241/8241), done.
Total 8241 (delta 5503), reused 0 (delta 0), pack-reused 0
Bitmap Indexes for Faster Clone and Fetch

A pack bitmap is a data structure stored alongside a pack file that allows Git to quickly compute which objects need to be sent to a client during a clone or fetch. Without bitmaps, Git must traverse the entire object graph for every pack operation. With bitmaps, it can answer reachability queries in near-constant time.

Create a pack with bitmap index

Bash
git repack -b --write-bitmap-index

# Or combined with the full repack:
git repack -A -d -b --write-bitmap-index

Pack files with bitmap

Text
.git/objects/pack/
  pack-a1b2c3d4e5f6789012345678901234567890.bitmap  ← bitmap index
  pack-a1b2c3d4e5f6789012345678901234567890.idx
  pack-a1b2c3d4e5f6789012345678901234567890.pack
Note
GitHub, GitLab, and other large-scale Git hosting services use pack bitmaps extensively. When you clone a large repository and it feels fast, bitmaps are a major reason why. The server can compute your clone pack in seconds rather than minutes because it does not need to walk the full object graph.
Measuring Before and After with count-objects

Check repo size before repack

Bash
git count-objects -vH

Before repack

Text
count: 6841          ← 6841 loose objects
size: 98.23 MiB     ← space used by loose objects
in-pack: 2105
packs: 4             ← fragmented into 4 pack files
size-pack: 31.45 MiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytes

Repack and check again

Bash
git repack -A -d -b --write-bitmap-index
git count-objects -vH

After repack

Text
count: 0              ← no more loose objects
size: 0 bytes
in-pack: 8946         ← all objects in one pack
packs: 1              ← single optimized pack
size-pack: 18.72 MiB  ← ~40% smaller due to better delta chains
prune-packable: 0
garbage: 0
size-garbage: 0 bytes
When to Manually Repack vs Letting gc Handle It

Scenario

Use

Routine maintenance on a developer workstation

Let git gc handle it automatically

Large import from SVN, Mercurial, or another VCS

git repack -A -d immediately after import

Hosting a repository that many users clone

git repack -A -d -b --write-bitmap-index

Repo has grown significantly from deleted large files

git filter-repo first, then git repack -A -d

Running a CI/CD system that clones frequently

Enable bitmaps on the server-side repo

After git filter-repo to remove secrets/large files

git repack -A -d to consolidate

Warning
Do not run `git repack` while other Git operations are accessing the same repository concurrently. Like `git gc --aggressive`, repack writes new pack files and deletes old ones during the operation. On a busy shared server, schedule repacks during off-hours or use a maintenance window.
Tip
For Git servers hosting many users, consider `git maintenance start` (Git 2.29+) which schedules incremental repacks as a background task — safer than a full repack and produces good results over time without requiring a maintenance window.