git multi-pack-index ties several packfiles together into one lookup, so Git stops hunting pack by pack. A repository that has accumulated packfile after packfile from years of pushes gets slower to query until something does exactly that. You will finish with a verified multi-pack-index (MIDX) for a repository, plus a safe way to decide whether expiry or repacking is actually appropriate. The examples match Git 2.43.0 from Ubuntu package git 1:2.43.0-1ubuntu7.3 and its matching git-man package.
sudo. Repack and expire change repository storage, so read their warnings first.Start from the repository whose object database you want to maintain. Replace the placeholder with an absolute path, or use . when you are already in the repository:
$ cd /path/to/repository
$ git --version
git version 2.43.0
$ git rev-parse --show-toplevel
/path/to/repository
$ git count-objects -v
That count is a useful baseline. In particular, packs tells you how many packfiles Git currently sees. A MIDX can be written even with only one pack, but it earns its keep once several packs accumulate between maintenance runs.
Checkpoint: if git rev-parse fails, stop and correct the path. Do not run maintenance commands from a directory that merely happens to share a project's name.
Write the index for the current repository with:
$ git multi-pack-index write
Git writes the MIDX below the repository's object store, normally .git/objects/pack/multi-pack-index. Its format records pack names, object IDs, and the pack and offset selected for each object; a duplicate object is represented once in the index, not once per pack.
Progress only shows when standard error is connected to a terminal, so a command running from a scheduler or with standard error redirected can look silent even while it works. That is a display default, not evidence the command did nothing. Ask for a definite choice with --progress or --no-progress instead:
$ git multi-pack-index --progress write
Checkpoint: verify the file itself rather than trusting its timestamp or a progress message.
Run the read-only check immediately after writing:
$ git multi-pack-index verify
$ printf '%s\n' $?
0
A zero status means the MIDX contents passed Git's verification. The command checks the index against the pack data it references; it does not repair a bad pack, fetch missing objects or repack anything. If verification reports an error, preserve the output and investigate the named pack before deleting a thing.
Run the same check again after copying a repository, restoring a backup, or completing any other storage operation. verify takes no pack-selection argument: it checks the current MIDX for the current object directory, nothing else.
When the same object occurs in more than one pack, Git normally breaks the tie in favour of the pack with the lowest modification time. Override that tie-breaker by naming a pack with --preferred-pack; the value must identify a pack containing at least one object:
$ find .git/objects/pack -maxdepth 1 -name 'pack-*.pack' -printf '%f\n'
pack-EXAMPLE.pack
$ git multi-pack-index write --preferred-pack=pack-EXAMPLE.pack
Use the pack basename your Git installation actually expects, then verify again. Choosing a preferred pack is a policy decision for later bitmap or pack-reuse behaviour, not a way to make a damaged pack trustworthy. With no operational reason to prefer one pack, leave the option out and keep Git's documented mtime rule.
A multi-pack bitmap can speed up object reachability operations, but writing one adds work and another index artefact to account for, so request it explicitly:
$ git multi-pack-index write --bitmap
$ git multi-pack-index verify
If a repacking process already took a reference snapshot, pass that readable file with --refs-snapshot=/path/to/refs-snapshot alongside --bitmap. The snapshot holds one object ID per line, with an optional leading + marking a preferred reference tip, and it may contain duplicate IDs. Do not invent a snapshot from arbitrary text: it is input to bitmap generation, not a general repository log. Use --no-bitmap to drop bitmap generation from a write command; that changes the index output and can affect later performance, so note the reason in your maintenance records.
For an alternate object store, point Git at the directory containing packs/:
$ git multi-pack-index --object-dir=/path/to/alternate-objects write
$ git multi-pack-index --object-dir=/path/to/alternate-objects verify
Git looks for the MIDX at /path/to/alternate-objects/pack/multi-pack-index and for packfiles in /path/to/alternate-objects/pack. The directory must already be a configured alternate of the current repository; if it is not, fix the repository's alternate-object configuration rather than writing an index against an unrelated object store.
Checkpoint: list the directory you intend to affect before running the command:
$ find /path/to/alternate-objects/pack -maxdepth 1 -type f -printf '%f\n' | sort
Warning: repack creates a new pack and changes which packfiles the MIDX references. The old, smaller packs become candidates for a later expiry, so take a backup, or confirm your normal repository backup is current, before running it on valuable data.
With a non-zero batch size, Git examines packs from oldest to newest and estimates each pack's useful size from the objects the MIDX selects. It keeps selecting packs until the requested batch size is reached or every pack has been considered; if only one pack gets selected, it does nothing. A zero batch size means every object the MIDX references goes into the new pack:
$ git multi-pack-index repack --batch-size=1g
$ git multi-pack-index verify
Do not assume 1g suits every repository; set it from measured disk and maintenance constraints. Packs carrying a .keep file are skipped when repack.packKeptObjects is false, so check that setting before expecting a kept pack to move.
Warning: expire deletes packfiles tracked by the MIDX that no longer contain any object the MIDX references, then rewrites the MIDX itself. It skips packs protected by a .keep file or cruft packs, but it is still a destructive storage operation. Confirm nothing is writing to the repository, and that you have a recoverable backup, before running it:
$ git multi-pack-index verify
$ git multi-pack-index expire
$ git multi-pack-index verify
$ git count-objects -v
Recovery: if the first verification fails, do not continue to expiry. If the final verification fails, stop further maintenance and restore the affected repository from backup, or investigate the exact pack Git names. There is no undo switch for a packfile expiry removes; recovery depends entirely on your backup or another complete copy of the object database.
--object-dir is not a generic output path. It must point to an alternate object directory whose packfiles live below packs/.verify instead of guessing.verify diagnoses the MIDX; it does not repair corrupt pack data.repack normally creates a new pack first. Leave expiry until the new MIDX has verified successfully and your backup position is clear.git multi-pack-index write completed and git multi-pack-index verify returned status 0.verify succeeded after any storage-changing command.