gitbutlerapp/gitbutler · error · anyhow::Error

No git repository found.

Error message

No git repository found.

What it means

End state of `setup_new_repo`: the current directory is not inside a git repository, so setup offers an interactive prompt ('Would you like to initialize a new one? [y/N]'). The error is returned when the user answers anything other than `y`, or when there is no interactive terminal at all (`prepare_for_terminal_input` yields None), in which case the prompt never appears.

Source

Thrown at crates/but/src/command/legacy/setup.rs:650

                "{}",
                t.hint
                    .paint("Initializing new repository and creating an empty first commit...")
            )?;
            let repo = gix::init(current_dir)?;

            create_empty_initial_commit(&repo)?;

            writeln!(
                &mut progress as &mut dyn FmtWrite,
                "{}",
                t.success
                    .paint("Initialized a new repository and created an empty first commit.\n")
            )?;
            return Ok(repo);
        }
    }

    Err(anyhow::anyhow!("No git repository found."))
}

fn create_empty_initial_commit(repo: &gix::Repository) -> anyhow::Result<()> {
    // In an unborn repo, this returns the well-known empty-tree id.
    // (It works even if the empty tree object isn’t physically in the ODB.)
    let empty_tree = repo.head_tree_id_or_empty().expect("repo access failed"); // -> Id<'_>
    let empty_tree = empty_tree.detach(); // -> ObjectId (optional; commit() accepts Into<ObjectId> anyway)

    // No parents for the first commit. Update HEAD (writes through to refs/heads/main).
    repo.commit(
        "HEAD",
        "Initial empty commit\n",
        empty_tree,
        std::iter::empty::<gix::hash::ObjectId>(),
    )?;

    Ok(())
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. cd into the actual repository clone (or pass its path) and rerun setup
  2. If you genuinely want a new repo there, run setup interactively and answer `y`, or just `git init` and make an initial commit yourself first
  3. In scripts, ensure the clone step succeeded and run `git init` before invoking setup non-interactively

Example fix

# before: ran in the wrong folder, prompt declined / no TTY
mkdir -p ~/work && cd ~/work && but setup

# after: enter the repo first
cd ~/work/project && but setup
Defensive patterns

Strategy: validation

Validate before calling

if gix::discover(std::env::current_dir()?).is_err() {
    if !std::io::stdin().is_terminal() {
        anyhow::bail!("not inside a git repository and no TTY to prompt; run 'git init' first");
    }
    // else let setup offer the init prompt
}

Try / catch

match run_setup(&mut ctx, &mut out) {
    Ok(_) => {}
    Err(err) if err.to_string() == "No git repository found." => {
        // guidance: cd into the clone, or git init, or answer 'y' when prompted
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Running `but setup` in a plain directory and declining the init prompt (answering N, n, empty enter, or any non-'y' input); running setup non-interactively (piped stdin, CI) where the prompt cannot be shown at all.

Common situations: Forgot to `cd` into the clone before running the tool; CI or cron pipelines with no TTY; expecting setup to find a repo that was never cloned; a clone step silently failed earlier in the script.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/2e186385e0df6ecd. Report an issue: GitHub.