jdx/mise · error

comparing checkpoints requires git

Error message

comparing checkpoints requires git

What it means

`mise dotfiles history diff` compares checkpoints stored in a git-backed snapshot store. If the store has no underlying git repository (git backend unavailable or store initialized without git), the comparison cannot run and run() bails immediately.

Solutions

  1. Install git and ensure it is on PATH
  2. Re-initialize the dotfiles history store so it is git-backed
  3. Verify the store directory contains a valid .git (or recreate it)

Example fix

// before: container without git
mise dotfiles history diff a b   // bails
// after
apt-get install -y git
mise dotfiles history diff a b
Defensive patterns

Strategy: fallback

Validate before calling

command -v git >/dev/null 2>&1 || echo 'git required for history diff'

Try / catch

if let Err(e) = diff_run() { if e.to_string().contains("requires git") { eprintln!("install git or use journal-only view"); } }

Prevention

When it happens

Trigger: Running `mise dotfiles history diff ...` when store.repo() returns None — git not installed, or the dotfiles history store was created in a mode without git backing.

Common situations: Git missing from PATH in minimal containers/CI; corrupted or partially deleted checkpoint store directory missing .git; user disabled git-backed snapshots.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/c536501494c1701a. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/dotfiles/history/diff.rs:48

    /// Print the full patch instead of a per-file summary
    #[usage(long, short)]
    patch: bool,

    /// Restrict to one path (a file or a directory)
    #[usage(long, value_name = "PATH")]
    path: Option<String>,

    /// Exit 1 when the two sides differ
    #[usage(long)]
    exit_code: bool,
}

impl HistoryDiff {
    pub(crate) async fn run(self) -> Result<()> {
        let (store, tracked, entries) = super::open().await?;
        let Some(repo) = store.repo() else {
            bail!("comparing checkpoints requires git");
        };
        let path = self.path.as_deref().map(display_arg);
        let (from, to, label) =
            if self.operation {
                if self.b.is_some() {
                    bail!("--operation takes at most one checkpoint reference");
                }
                let outcome = match &self.a {
                    Some(reference) => super::resolve(reference, &entries, None)?,
                    None => entries
                        .iter()
                        .rev()
                        .find(|entry| entry.checkpoint.operation.is_some())
                        .cloned()
                        .ok_or_else(|| eyre::eyre!("no recorded operation"))?,
                };
                let operation =
                    outcome.checkpoint.operation.as_ref().ok_or_else(|| {

View on GitHub (pinned to 533346cc37)