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-refs: Pack References for Efficient Storage

Understand packed refs, loose refs, selection patterns, pruning behavior, and automatic ref packing without confusing ref storage with object packing.

Levels: Advanced ~25 min read

Advanced

Why refs can be packed

Git traditionally stores refs such as branch and tag names as individual files below `.git/refs`. Repositories with many long-lived refs can instead store refs in `.git/packed-refs`. A packed ref is still a ref: packing changes the storage representation, not the ref name or the commit it identifies.

bash
git show-ref
find .git/refs -type f -print | sort
cat .git/packed-refs 2>/dev/null || true

Quick check

What does packing a ref change?

Pack all eligible refs

`git pack-refs --all` asks Git to pack all refs that are eligible under the command's rules. Symbolic refs and broken refs are not packed. After packing, the ref remains usable through normal commands such as `git show-ref`, even though its loose ref file may no longer exist.

bash
git pack-refs --all
git show-ref
cat .git/packed-refs

Quick check

After `git pack-refs --all`, what should a normal ref lookup do?

Default packing and active branches

Without `--all`, `git pack-refs` normally packs tags and refs that are already packed while leaving actively changing branch tips alone. This reflects a useful storage distinction: tags are generally stationary, while branch heads are frequently updated. A later `git pack-refs` can pack eligible refs again.

bash
git pack-refs
git show-ref
find .git/refs -type f -print | sort

Quick check

Why can a branch remain as a loose ref after a default `git pack-refs`?

Keep loose refs with --no-prune

Packing normally prunes the loose ref files that were successfully packed. `--no-prune` suppresses that cleanup. The same ref can therefore be represented in both places temporarily. This is a storage-detail experiment, not a second independent ref.

bash
git pack-refs --all --no-prune
find .git/refs -type f -print | sort
cat .git/packed-refs

Quick check

What does `--no-prune` control?

Select refs with --include and --exclude

`--include <pattern>` and `--exclude <pattern>` let you control which refs are selected. Patterns are glob patterns over ref names. When both apply to a ref, exclusion takes precedence. Using `--include` also changes the normal default selection behavior, so do not assume that tags are automatically included when an explicit include pattern is present.

bash
git pack-refs --include 'refs/heads/feature/*'
git pack-refs --all --exclude 'refs/heads/feature/*'

Quick check

If a ref matches both an include and an exclude pattern, which wins?

Automatic packing with --auto

`--auto` lets Git decide whether packing is warranted based on the current ref-storage state. Its behavior depends on the repository's ref format and may evolve as ref storage implementations evolve. Treat it as a policy-driven optimization rather than a command that promises a fixed set of refs will be packed.

bash
git pack-refs --auto

Quick check

What is the important property of `--auto`?

Packed refs are still ordinary refs

Packing does not create a new namespace of refs. Commands that read refs continue to use the same names. If a branch is updated later, Git can create a loose ref again; a subsequent packing operation can optimize the ref storage again. This is why scripts should use Git's ref interfaces instead of assuming every branch or tag has a file under `.git/refs`.

bash
git rev-parse HEAD
git show-ref --heads
git show-ref --tags

Quick check

Which assumption should a script avoid?

Boundaries with nearby commands

`git pack-refs` optimizes ref storage. It is different from `git refs`, which provides low-level ref operations; `git reflog`, which manages reflog records; `git repack`, which reorganizes object packfiles; and `git multi-pack-index`, which indexes multiple object packfiles. These mechanisms can interact in repository maintenance, but they solve different storage problems.

bash
git show-ref
git pack-refs --all
git count-objects -v
git multi-pack-index verify

Quick check

Which command is specifically for reorganizing object packfiles rather than ref storage?

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.