In short: it refuses to run unless it is at the head operation. It then asks the operation store to delete
operation and view files not reachable from the current operation, then calls the commit backend's own
gc with the commit index's heads. The Git backend rewrites jj's
refs/jj/keep/* refs to match those heads and runs git gc; the simple backend does nothing. Anything newer
than the cutoff (two weeks ago, or now with --expire=now) is kept, so another process's fresh work
isn't deleted. It records no operation.
The command is cmd_util_gc. Its help text: "Run
backend-dependent garbage collection." To reclaim old operations, upstream says to run
jj op abandon ..<some old operation> first (source). It is
the Gc variant of UtilCommand (source,
dispatch).
1. Command-line surface
| Flag | Type | Default | Meaning |
|---|---|---|---|
--expire | string | 2 weeks | "Time threshold". Only now is accepted; anything else is the error "--expire only accepts 'now'" (source, check). |
Run with --at-op set to anything but @, it fails with "Cannot garbage collect from a
non-head operation" (source, test). The
global flags are on the CLI page.
3. End-to-end flow
4. Core architecture touchpoints
| Piece | Role here |
|---|---|
OpStore::gc | Keeps everything reachable from the given heads plus anything newer than keep_newer, which "mitigates a risk of deleting new heads created concurrently by another process". The simple store does this by file mtime, and notes a remaining race if an existing file is renewed (source). |
Index::all_heads_for_gc | The heads of every commit the index knows at this operation, which are the commits to preserve. The Git backend filters out the root commit (source). |
Backend::gc | The commit backend's own garbage collection, an async trait method: "All commits reachable from heads won't be removed," and anything newer than keep_newer is kept too. The command calls it after the operation store's gc (source). The simple backend's version does nothing (source); the secret backend passes it to the backend it wraps (source). |
refs/jj/keep/ | The refs that stop git gc from pruning commits only jj knows about. Each kept ref is named after the commit it points to (source); stale ones are deleted in one batched ref edit (source). |
The git executable | Run as a subprocess in the Git directory. Its output goes straight to the terminal; a TODO says it should go through the UI layer (source). |
| Operation log | Pruned but never appended to: the command starts no transaction (source). After jj op abandon ..@- and jj util gc --expire=now, the abandoned operation's file is gone (test). |