git index-pack rebuilds the .idx file a pack needs, or checks a pack you just received before you trust it. A missing or corrupt index will stop a pack dead until you run it. The examples match Git 2.43.0 from Ubuntu package git-man 1:2.43.0-1ubuntu7.3, installed on the system used for this guide. Allow about fifteen minutes.
sudo only when the pack directory is deliberately owned by another account, and check the path carefully before writing there.Confirm the version and syntax before touching a pack. These are ordinary, read-only commands:
$ git --version
git version 2.43.0
$ git index-pack -h
usage: git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])
The command reads a .pack file and builds its matching .idx file. It does not unpack objects into loose files. A pack and its index can then live in a repository's objects/pack/ directory.
Checkpoint: identify the exact pack you intend to process. Do not use a wildcard until you have inspected what it matches.
$ PACK=/path/to/objects/pack/pack-0123456789abcdef0123456789abcdef01234567.pack
$ test -f "$PACK" && printf 'pack found: %s\n' "$PACK"
pack found: /path/to/objects/pack/pack-0123456789abcdef0123456789abcdef01234567.pack
When the file name ends in .pack, the default output name is the same basename with .idx. If the index is missing or damaged, rebuilding it changes that directory, so take a backup or make sure the pack is recoverable first.
$ git index-pack --strict --rev-index "$PACK"
0123456789abcdef0123456789abcdef01234567
The hexadecimal line is the pack checksum used in the pack and index names. With --strict, Git rejects broken objects or links rather than creating an index for a suspect pack. --rev-index also creates a reverse index beside it:
$ test -f "${PACK%.pack}.idx" && echo 'index created'
index created
$ test -f "${PACK%.pack}.rev" && echo 'reverse index created'
reverse index created
$ git verify-pack -v "${PACK%.pack}.idx" | tail -n 1
non delta: 3 objects
The final verify-pack line is data-dependent, so your object count will differ. A successful command and an existing index are the checks that matter. Skip --rev-index if you do not need reverse-index data; the option overrides the repository's pack.writeReverseIndex setting for this run.
Use -o when the generated index must not sit beside the pack. This suits staging or testing, but it leaves the original pack untouched and does not make the custom index the repository's active one:
$ INDEX=/tmp/pack-check.idx
$ git index-pack --strict --rev-index -o "$INDEX" "$PACK"
0123456789abcdef0123456789abcdef01234567
$ test -f "$INDEX" && echo 'custom index created'
custom index created
Do not point -o at an index already used by a different pack. An index describes one particular pack, so overwriting a valid index with an unrelated one can make later Git operations fail. If this was only a test, remove the temporary file after inspection:
$ rm -f -- "$INDEX"
$ test ! -e "$INDEX" && echo 'temporary index removed'
temporary index removed
Use --stdin when another process or a file transfer supplies the pack stream. Git writes a copy to the destination you provide, then builds the index from that copy. The destination must be writable:
$ mkdir -p /path/to/objects/pack
$ cat /path/to/incoming.pack | git index-pack --stdin --strict --rev-index \
/path/to/objects/pack/received.pack
0123456789abcdef0123456789abcdef01234567
$ ls -1 /path/to/objects/pack/received.*
received.idx
received.pack
received.rev
For a real transfer, replace cat with the actual producer. Git's output is the checksum, not a success message you can rely on parsing as a file name, so check the expected files explicitly.
If you omit the destination, Git chooses a pack name from the content and writes into the current repository's objects/pack/ directory. That suits Git's own receive workflows, but it makes the destination less obvious. Use an explicit path when working by hand.
A concurrent git repack can remove a newly imported pack before a reference points to its objects. Add a keep file while another process completes that hand-off:
$ cat /path/to/incoming.pack | git index-pack --stdin \
--strict --rev-index --keep='manual import 2026-09-24' \
/path/to/objects/pack/received.pack
keep 0123456789abcdef0123456789abcdef01234567
$ ls -1 /path/to/objects/pack/received.*
received.idx
received.keep
received.pack
received.rev
The .keep file is a coordination lock, not permanent metadata. Finish the reference update or other consumer operation first, then remove only the keep file you created:
$ rm -f -- /path/to/objects/pack/received.keep
$ test ! -e /path/to/objects/pack/received.keep && echo 'keep file removed'
keep file removed
Warning: do not remove another process's keep file to make a repack proceed. If you are unsure who owns it, leave it in place and investigate. A stale keep file normally just costs storage; deleting an active one can create a race.
A thin pack omits base objects that the receiving repository is expected to already have. It can only be repaired while reading from standard input:
$ git pack-objects --stdout --thin < object-list \
| git index-pack --stdin --fix-thin --strict \
/path/to/objects/pack/repaired.pack
That placeholder input is deliberately not a complete producer. Use the exact pack-producing workflow that created the thin pack, and make sure the required base objects are already available. --fix-thin is unnecessary with a normal complete pack, and using it without --stdin is invalid.
Outside a repository, Git assumes SHA-1 unless you specify another supported object format. Inside a repository it follows extensions.objectFormat. SHA-1 and SHA-256 repositories are not interchangeable, and --object-format cannot be combined with --stdin in this Git release. Do not guess the hash format from a shortened checksum.
-o, but check that the file is really a pack before renaming it.--strict. Stop. Keep the original files, get the pack again from a trusted source, or investigate with the repository owner. Do not suppress the check just to make the command exit successfully..idx, optional .rev and any .keep file share the same basename. A reverse index is optional; the main index is not..pack file..idx was verified, and --strict was used on untrusted or recovered data.--stdin only for a stream, and --fix-thin only for a thin pack..keep file only across a real hand-off, then removed the one you owned.