gitbutlerapp/gitbutler · error
The repository at has no .git directory. GitButler requires…
Error message
The repository at {} has no .git directory. GitButler requires a .git directory. What it means
Thrown when `AddProjectOutcome::NoDotGitDirectory` is returned. The path looks like a candidate repository but no `.git` directory (or file for worktrees/submodules) was found, so GitButler cannot locate the git metadata.
Solutions
- Verify the repo with `git -C <path> status`; if it fails, run `git init` or clone the project.
- Restore the deleted `.git` directory (re-clone and copy, or re-clone entirely).
- Point setup at the actual repository root, not a subfolder outside it.
Example fix
// before but setup ~/downloads/myrepo-1.0 // after git clone <url> ~/code/myrepo but setup ~/code/myrepo
Defensive patterns
Strategy: validation
Validate before calling
if (!fs.existsSync(path.join(repoPath, '.git'))) {
throw new Error(`${repoPath} has no .git; run git init or clone first`);
} Type guard
function hasGitDir(p: string): boolean {
try { return fs.existsSync(path.join(p, '.git')); } catch { return false; }
} Try / catch
try {
await run(['but', 'setup', repoPath]);
} catch (e) {
if (String(e).includes('no .git directory')) {
console.error('This is not a git checkout; clone or git init first.');
}
throw e;
} Prevention
- Never delete .git to 'reset' a repo; re-clone instead.
- Don't register extracted source archives; clone from the remote.
- Confirm with `git status` before onboarding a folder.
When it happens
Trigger: Running setup on a plain directory that is not a repo, or a directory where `.git` was deleted, or a downloaded source archive (no git metadata).
Common situations: Extracting a zip/tarball of a project and trying to register it; `.git` removed by cleanup scripts; initializing a folder without `git init`.
Related errors
- `but setup` cannot run from a linked worktree; run it from…
- No git repository found at
- No git repository found - run `but setup --init` to…
- No HEAD reference found for remote
- Repository has no working directory
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/6f0b2ba7b911afe9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/command/legacy/setup.rs:273
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NotADirectory => Err(anyhow::anyhow!(
"The path {} is not a directory",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::BareRepository => Err(anyhow::anyhow!(
"The repository at {} is bare. GitButler requires a non-bare repository.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NonMainWorktree => Err(anyhow::anyhow!(
"The repository at {} is a non-main worktree. GitButler requires the main worktree.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!(
"The repository at {} has no working directory. GitButler requires a working directory.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NoDotGitDirectory => Err(anyhow::anyhow!(
"The repository at {} has no .git directory. GitButler requires a .git directory.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(
"The repository at {} uses the currently unsupported reftable reference format.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NotAGitRepository(_) => Err(anyhow::anyhow!(
"The path {} is not a git repository.",
repo_path.display()
)),
}?;
// A ported project can keep its target in Git config while the legacy `virtual_branches.toml`
// / database store is empty — for example after that store was reset. The check below would
// then see a target and report "already set up", but the workspace needs the legacy default
// target to work. Repair it from the workspace first so setup isn't a dead end.
if gitbutler_branch_actions::base::bootstrap_default_target_if_missing(&*ctx)?View on GitHub (pinned to 58e5313667)