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.
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.
git show-ref
find .git/refs -type f -print | sort
cat .git/packed-refs 2>/dev/null || trueQuick 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.
git pack-refs --all
git show-ref
cat .git/packed-refsQuick 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.
git pack-refs
git show-ref
find .git/refs -type f -print | sortQuick 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.
git pack-refs --all --no-prune
find .git/refs -type f -print | sort
cat .git/packed-refsQuick 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.
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.
git pack-refs --autoQuick 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`.
git rev-parse HEAD
git show-ref --heads
git show-ref --tagsQuick 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.
git show-ref
git pack-refs --all
git count-objects -v
git multi-pack-index verifyQuick 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.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.