Skip to content

Packs and maintenance

Objects live loose, one file each, or in packs: a .pack of compressed objects with an .idx index beside it. These commands look at packs and run girt’s maintenance, which keeps every object something still reaches and removes what nothing does. Maintenance deletes data, so its destructive phases each need their own flag and an explicit --yes. None of the maintenance commands, nor pack list and pack verify, has an exact Git counterpart, so --git doesn’t change their output. The library side is in Maintenance and GC and the safety model.

girt maintenance plan works out what maintenance would keep, without changing anything. Roots are every reference, every reflog entry, HEAD and the index; everything they reach is retained.

$ girt maintenance plan
roots 17
retained 17
reachable 17
unreachable-loose 0
unreachable-packed 0
protected-packs 0
alternates 0

roots counts the distinct starting points: reference and reflog values, HEAD, index entries and recent loose objects. reachable counts the objects visited from them, and retained those still required once reflog expiry is applied. protected-packs counts packs that maintenance won’t retire, because of a .keep file or a recent modification time, and alternates the borrowed object stores, which girt reads but never prunes.

Pack retained objects (girt maintenance repack)

Section titled “Pack retained objects (girt maintenance repack)”

girt maintenance repack writes every retained object into one new pack and prints its path, object count and size. The demo repository has only loose objects until this runs. It deletes nothing: the old packs and loose objects stay until maintenance run --retire-packs or --prune-loose removes them.

$ girt maintenance repack
/home/me/demo/.git/objects/pack/pack-8e2d3d02ad0532e0364ede2302d4dcc7db3d743a.pack 17 1118

girt pack list prints each pack’s path, object count and .pack size in bytes: the repository’s own packs first, then those of its alternates. keep, promisor and alternate follow when they apply.

$ girt pack list
/home/me/demo/.git/objects/pack/pack-8e2d3d02ad0532e0364ede2302d4dcc7db3d743a.pack 17 1118

girt pack verify checks every pack’s checksums and decodes every object in it. It prints ok, or the first error and exits 1. Where git verify-pack checks one pack, this checks all of them.

$ girt pack verify
ok

girt pack reindex <pack> rebuilds a pack’s .idx from the .pack alone and reports whether the index was created, replaced or unchanged, with the pack checksum and object count. With --git it prints only the checksum, as git index-pack does.

$ girt pack reindex .git/objects/pack/pack-8e2d3d02ad0532e0364ede2302d4dcc7db3d743a.pack
unchanged 8e2d3d02ad0532e0364ede2302d4dcc7db3d743a 17

Delete what nothing retains (girt maintenance run)

Section titled “Delete what nothing retains (girt maintenance run)”

girt maintenance run runs the destructive phases you name: --expire-reflogs drops old reflog records, --retire-packs replaces old packs with one pack of their retained objects, and --prune-loose deletes unreachable loose objects. Without --yes it prints the plan and what each phase would remove, and stops.

$ girt maintenance run --expire-reflogs --retire-packs
roots 17
retained 17
…
would-expire-reflog-records 0
would-retire-packs 0
dry run: pass --yes to run (nothing else may use the repository)

Passing --yes is your statement that nothing else, whether Git, jj, an editor or another girt, reads or writes the repository while maintenance runs; girt has no repository-wide lock to check it. Loose objects and packs less than two weeks old are always kept, and reflog records expire after 90 days, or 30 when what they point at is unreachable. The phases always run in the same order: reflogs, then packs, then loose objects.