Expand description
mkit reflog [<ref>] — read-only view over the persisted
ref-history journal (issue #231).
§What the journal actually records
mkit’s ref-history is the per-branch, append-only commit-history
MMR (mkit_core::history::CommitHistory, the refs-history.lock
journal written by write_ref_recording_history). It records one
leaf per branch ref WRITE, not one leaf per commit that ends up
reachable from the tip. For most operations — a plain commit,
branch creation, merge, cherry-pick, amend, a rebase --abort
rollback, fetch/pull tip update — each new commit corresponds to
exactly one ref write, so “one leaf per advance” and “one leaf per
commit” coincide in practice.
rebase is the documented exception (issue #648): a
multi-commit rebase detaches HEAD for the whole operation and moves
it once per replayed commit (refs::write_head_detached, NOT
write_ref_recording_history), then performs exactly ONE branch ref
write at finalize. A rebase that replays five commits therefore
appends exactly one leaf, not five — the intermediate replayed
commits are perfectly valid, reachable, mkit-created commits that
were simply never in scope for per-commit journaling. The same gap
applies to any future op that moves detached HEAD through multiple
commits before a single branch-ref finalize. The journal therefore
stores:
- the count of recorded ref writes (
len()), and - a tamper-evident root plus per-leaf inclusion proofs.
It deliberately does not store what a Git reflog stores: there
is no op label, no old→new pair, no per-entry timestamp or message,
and — crucially — the leaf digests are BLAKE3 values with the leaf
position mixed in, so the original commit hashes cannot be read
back out of the MMR. The MMR can only confirm a hash you already
hold (via verify_inclusion).
§What mkit reflog therefore surfaces
Because the readable hashes can only come from the object store, not
the MMR, reflog walks the branch tip’s first-parent chain
(newest → oldest) — the same reconstruction
history::rebuild_from_chain uses — and presents it as the branch’s
movement history, addressed <branch>@{N} with @{0} = current
tip. On a build with --features history-mmr it additionally
cross-checks each commit against the journaled MMR root: it asks
the journal to confirm, via an inclusion proof, that the commit was
recorded as a branch advance at some leaf position. The
recorded-advance count is reported in the summary line. The check is
rewrite-robust — a reachable commit shows [journaled] as long as it
was journaled at some point, even after a later amend/reset shifted
the journal’s leaf count past the reachable chain length.
A reachable commit that does not verify is printed as [not journaled], deliberately worded to describe absence rather than
imply tampering: per the rebase gap above, an intermediate
rebase-replayed commit is expected to show this marker every time —
it is a normal consequence of one-leaf-per-ref-write, not evidence
of anything wrong with the commit or the journal. A [not journaled]
marker on a commit that was NOT created by a mid-rebase replay (e.g.
a plain commit, or a rebase’s own finalize tip) is the more
interesting case worth investigating.
This is not a full Git reflog: @{N} indexes the reachable
first-parent chain (which drops superseded commits — e.g. after an
--amend or a reset the old tip is no longer listed), not the raw
append log of every movement. See the help text / man mkit for the
exact contract.
Read-only: this command never mutates refs, the journal, or any object.