Chapter 22Lesson 02~185 minutes

Commit-Graphs, Multi-Pack Indexes, Maintenance, Garbage Collection, and Performance: Guided Hands-On Workflow and Core Operations

Generate a disposable repository with multiple packs, capture timings/object counts, write and verify commit-graph/MIDX structures, inspect pack storage, register isolated maintenance, and run safe repack/GC operations.

Hands-on maintenancePack verificationMIDXSafe GC

Learning objectives

  • Measure commit/object/pack state before optimizing.
  • Create several packfiles and validate them with verify-pack.
  • Write/verify a MIDX and a changed-path commit-graph.
  • Register maintenance without modifying real global configuration or OS scheduler state.
  • Run explicit maintenance and non-pruning GC while verifying history invariants.

1. Create a disposable repository large enough to show storage transitions

The lab deliberately creates many small commits in batches. Each batch is repacked separately so the repository accumulates several packfiles before you create a multi-pack index.

Git Bash, Bash, or zsh

mkdir git-performance-lab
cd git-performance-lab
git init -b trunk repo
cd repo
git config user.name "Performance Lab"
git config user.email "performance-lab@example.invalid"

mkdir data
for i in $(seq 1 20); do
  printf "seed=%s\n" "$i" > "data/file-$i.txt"
done
git add data
git commit -m "seed repository"

PowerShell setup alternative

New-Item -ItemType Directory git-performance-lab | Out-Null
Set-Location git-performance-lab
git init -b trunk repo
Set-Location repo
git config user.name "Performance Lab"
git config user.email "performance-lab@example.invalid"

New-Item -ItemType Directory data | Out-Null
1..20 | ForEach-Object { "seed=$_" | Set-Content "data/file-$_.txt" }
git add data
git commit -m "seed repository"

2. Capture a baseline before optimizing

git status --short --branch
git rev-parse HEAD
git rev-list --count HEAD
git count-objects -vH
git fsck --full

Record the current tip OID. Every maintenance operation in this lesson should preserve that commit and the branch history. Storage files may change; repository meaning should not.

3. Measure repeatably, but do not overinterpret tiny timings

Bash-family shells

time git rev-list --count HEAD
time git log --oneline -- data/file-1.txt >/dev/null
time git status --porcelain >/dev/null

PowerShell

Measure-Command { git rev-list --count HEAD | Out-Null }
Measure-Command { git log --oneline -- data/file-1.txt | Out-Null }
Measure-Command { git status --porcelain | Out-Null }

Run each command several times. The first run can include cold filesystem/page-cache costs; later runs can benefit from warm caches. This training repository is intentionally small, so “after” may not be faster even when an acceleration structure is working correctly.

4. Generate four history batches and create multiple packfiles

Git Bash / Bash / zsh

for batch in 1 2 3 4; do
  for n in $(seq 1 30); do
    printf "batch=%s item=%s\n" "$batch" "$n" >> "data/file-$(( (n % 20) + 1 )).txt"
    git add data
    git commit -m "batch $batch change $n" >/dev/null
  done
  git repack -d
  git count-objects -vH
done

PowerShell

1..4 | ForEach-Object {
  $batch = $_
  1..30 | ForEach-Object {
    $n = $_
    $file = ($n % 20) + 1
    "batch=$batch item=$n" | Add-Content "data/file-$file.txt"
    git add data
    git commit -m "batch $batch change $n" | Out-Null
  }
  git repack -d
  git count-objects -vH
}

git repack -d in this disposable lab packs new loose objects and removes redundant packs/loose duplicates that the new pack makes unnecessary. Because earlier packs already contain older objects, the batches can leave several packs.

Scope: manual repack is being demonstrated on generated data only. On production repositories, prefer normal automatic/maintenance behavior unless measurements justify an explicit repack plan.

5. Inspect pack count and verify each pack

git count-objects -vH
ls .git/objects/pack/

for idx in .git/objects/pack/*.idx; do
  git verify-pack "$idx"
done

PowerShell pack verification alternative

git count-objects -vH
Get-ChildItem .git/objects/pack

Get-ChildItem .git/objects/pack/*.idx | ForEach-Object {
  git verify-pack $_.FullName
}

verify-pack validates the pack index and associated pack. With -v it can also show object types, compressed sizes, offsets, and delta-chain depths. Do not parse its verbose human output as a long-term application protocol unless the script is explicitly tied to the documented format/version.

6. Write and verify a multi-pack index

git multi-pack-index write
git multi-pack-index verify
git count-objects -vH

The number of logical commits/objects does not change. The MIDX adds a lookup structure across the packs. Current Git can also write incremental/version-2 MIDX layers, but those newer formats have mixed-version compatibility considerations; this mandatory lab uses the broadly supported basic write/verify path.

7. Write a commit-graph with changed-path information

git commit-graph write --reachable --changed-paths
git commit-graph verify

git log --oneline -- data/file-1.txt >/dev/null
git rev-list --count HEAD

The commit-graph records reachable commits plus optional changed-path Bloom filters. It should not alter HEAD, refs, commit contents, or working-tree files.

8. Run explicit maintenance tasks one at a time

git maintenance run --task=commit-graph
git maintenance run --task=loose-objects
git multi-pack-index verify
git commit-graph verify

Passing --task makes the requested task explicit and avoids relying on implicit strategy configuration during a teaching lab.

9. Register maintenance using an isolated config file

Normal git maintenance register uses the user's global Git configuration. The lab avoids changing your real global config by supplying a disposable config file:

git maintenance register --config-file ../maintenance-demo.config

git config --file ../maintenance-demo.config --get-all maintenance.repo
git config --show-origin --get maintenance.strategy
git config --show-origin --get maintenance.auto

Current Git registration records the repository and, when no maintenance strategy was already configured, uses the incremental strategy for background-maintenance-style operation. It also disables foreground auto-maintenance for the registered repository. Exact configuration details should be verified on the installed Git version.

10. Understand scheduler integration without modifying your machine scheduler

git maintenance start installs user-level scheduled maintenance through a platform scheduler. Current Git supports scheduler choices such as systemd timers or cron on Linux, launchctl on macOS, and Task Scheduler on Windows. That changes user-level system configuration, so it is not required in this lab.

# Inspection only: see what the current repository registered.
git config --file ../maintenance-demo.config --list --show-origin

# Optional on a disposable machine/profile only:
# git maintenance start --scheduler=auto

11. Demonstrate incremental repack through maintenance

git multi-pack-index write
git maintenance run --task=incremental-repack
git multi-pack-index verify
git count-objects -vH

The task uses the multi-pack-index mechanism to consolidate smaller packs gradually. A later expire step can remove packs that the MIDX no longer references. The exact pack count may vary because the selection is size-dependent.

12. Run GC only with pruning disabled in this disposable lab

GC can expire recovery data under normal expiry rules. For the teaching run, explicitly disable pruning and keep the repository disposable.
BEFORE=$(git rev-parse HEAD)
git gc --no-prune
AFTER=$(git rev-parse HEAD)

test "$BEFORE" = "$AFTER"
git fsck --full
git count-objects -vH

gc --no-prune can still reorganize packs, refs, and auxiliary structures, but it does not prune loose unreachable objects. The branch tip must remain unchanged.

13. Compare measurements after maintenance

git rev-list --count HEAD
git count-objects -vH
git commit-graph verify
git multi-pack-index verify 2>/dev/null || echo "MIDX may have been replaced/removed by later GC"

time git rev-list --count HEAD
time git log --oneline -- data/file-1.txt >/dev/null
time git status --porcelain >/dev/null

A later full GC may consolidate pack layout enough that a MIDX is unnecessary or regenerated differently. Treat the absence of a previously written acceleration file as an implementation outcome to re-measure—not as history loss.

14. Challenge — choose the narrowest operation

  1. You have many loose objects but one healthy pack. Which evidence command comes first?
  2. You have many packs but do not want an all-into-one repack. Which maintenance mechanism is designed for gradual consolidation?
  3. Path-history queries are expensive. Which auxiliary structure can add changed-path Bloom filters?
  4. You want to validate pack storage without changing it. Which command?
  5. You want maintenance registration without touching your real global config in a lab. Which register option?

15. Cleanup

Confirm the parent directory before recursive deletion.
cd ../..
pwd
rm -rf git-performance-lab

PowerShell equivalent: Set-Location ../..; Remove-Item -Recurse -Force git-performance-lab.

16. Knowledge check

Question 1. What state should remain unchanged when you write a MIDX or commit-graph?

Question 2. Why is one timing run insufficient?

Question 3. What does git verify-pack validate?

Question 4. Why was git gc --no-prune used in the lab?

Question 5. Why is git maintenance start optional here?

17. Summary

You measured object storage, created multiple packs, verified them, added MIDX and commit-graph acceleration, registered isolated maintenance state, ran explicit maintenance tasks, and demonstrated non-pruning GC. The key invariant was that optimization changes representation, not repository meaning.

Next

Turn mechanics into an operating policy

Lesson 3 maps maintenance strategies, auto-maintenance thresholds, commit-graph/MIDX controls, FSMonitor, untracked cache, and Scalar to developer, CI, and server contexts.

Authoritative references

 git-count-objects
 git-repack
 git-verify-pack
 git-multi-pack-index
 git-maintenance

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.