Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Git pack-objects: Construct Pack Archives

Construct Git pack archives from object lists and revisions, control object selection and delta compression, and understand the boundary between low-level pack construction and repository repacking.

Levels: Advanced ~35 min read

Advanced

What `git pack-objects` actually does

`git pack-objects` reads objects or revision arguments and writes a packed archive. A pack stores objects together, potentially using delta compression, and normally has a matching `.idx` file for random access. This is the low-level pack constructor; ordinary users normally reach pack creation through higher-level commands such as `git repack`.

bash
git rev-list --objects --all | git pack-objects --stdout > objects.pack

Quick check

Which operation is owned by `git pack-objects`?

Explicit object lists

Without `--revs`, the command reads object names from standard input. The names can be supplied directly or obtained from another plumbing command such as `git rev-list --objects`. With `--stdout`, the binary pack is written to standard output instead of a named pack file.

bash
git rev-list --objects HEAD | git pack-objects --stdout > selected.pack

Quick check

What does `--stdout` change?

Writing a pack and index pair

When a base name is supplied instead of `--stdout`, `pack-objects` writes a `.pack` and corresponding `.idx` pair. The final pack name incorporates a hash derived from the pack contents, and the pack name is also reported on standard output.

bash
git rev-list --objects --all | git pack-objects .git/objects/pack/pack-from-lesson

Quick check

What does a base-name invocation produce?

Revision mode with `--revs`

`--revs` changes the standard-input interpretation: Git reads revision arguments in the same style used by `git rev-list --objects`. This lets the command perform the reachability walk itself. `--all` implies `--revs` and includes objects reachable from all refs under `refs/`.

bash
printf '%s\n' HEAD | git pack-objects --revs --stdout > head.pack
git pack-objects --all --stdout </dev/null > all-refs.pack

Quick check

What does `--all` imply?

Only unpacked objects

`--unpacked` also implies `--revs`, but limits the resulting object set to objects that are not already packed. This is useful when constructing an incremental pack from a repository that already has packfiles.

bash
printf '%s\n' HEAD | git pack-objects --revs --unpacked --stdout > newly-unpacked.pack

Quick check

What does `--unpacked` restrict?

Incremental and local packing boundaries

`--incremental` ignores objects already in a pack. `--local` ignores objects borrowed from an alternate object store. These options address which existing object storage is eligible for the new pack; they do not mean the same thing as reachability.

bash
printf '%s\n' HEAD | git pack-objects --revs --incremental --stdout > incremental.pack
printf '%s\n' HEAD | git pack-objects --revs --local --stdout > local-only.pack

Quick check

What is the important distinction?

Delta compression controls

`--window=<n>` controls how many candidate objects are considered for delta compression, while `--depth=<n>` limits the maximum delta-chain depth. `--delta-base-offset` permits offset-based delta references and can make packs smaller, at the cost of compatibility with very old Git versions. The current documentation gives defaults of window 10 and depth 50.

bash
git rev-list --objects --all | git pack-objects --stdout --window=5 --depth=10 --delta-base-offset > tuned.pack

Quick check

Which option limits maximum delta-chain depth?

Reuse and output controls

`--no-reuse-delta` tells Git to compute deltas rather than reusing existing delta relationships. `--no-reuse-object` goes further and prevents reuse of existing object data; it implies `--no-reuse-delta`. `--non-empty` suppresses creation of an empty pack, while `-q` suppresses progress output and `--progress` forces it.

bash
git rev-list --objects --all | git pack-objects --stdout --no-reuse-delta > fresh-deltas.pack
git rev-list --objects --all | git pack-objects --stdout --no-reuse-object > recompressed.pack

Quick check

Which option implies `--no-reuse-delta`?

Annotated tags and pack completeness

`--include-tag` includes an annotated tag object when the object it refers to is otherwise included in the resulting pack. This can matter when a pack is being prepared for transfer to a native Git client.

bash
printf '%s\n' HEAD | git pack-objects --revs --include-tag --stdout > with-tag.pack

Thin packs and the `index-pack` boundary

A thin pack can omit common base objects and therefore is not self-contained. The official documentation restricts `--thin` to `--stdout` use and points to `git index-pack --fix-thin` for restoring the self-contained property after reception. This lesson deliberately demonstrates the boundary rather than using a thin pack as an ordinary local archive.

bash
git rev-list --objects HEAD | git pack-objects --stdout --thin > transfer.pack

Quick check

Why is a thin pack special?

Do not confuse `pack-objects` with `repack`

`git pack-objects` is the low-level pack constructor. `git repack` orchestrates repository-wide pack creation and replacement, including pack cleanup policies. `git index-pack` builds an index for an existing pack, and `git show-index` reads that index. `git verify-pack` verifies an existing pack/index pair. `git pack-refs` is unrelated: it reorganizes refs rather than object packs.

Quick check

Which command is the higher-level repository repacking operation?

Current Git 2.56.0 surface versus local verification

The live Git 2.56.0 manual is broader than the Git 2.47.3 executable used for local verification. The current manual documents newer interfaces including `--stdin-packs`, `--path-walk`, and `--name-hash-version=<n>`, as well as current partial-clone and cruft-related options. They are intentionally not presented here as runnable learner commands because this environment cannot execute and verify them locally. This preserves the project rule: current official documentation defines the semantic target, while every command we teach as runnable must be locally verified.

Practice what you learned

Use the dedicated Git code-completion exercise for this lesson.

Was this page helpful?

Mark this learning resource complete to track your learning progress.