gitbutlerapp/gitbutler · error
no .git directory found in repository
Error message
no .git directory found in repository
What it means
AddProjectOutcome::NoDotGitDirectory mapped through try_project: the path is a directory but no .git entry (directory or gitdir-pointer file) could be found for it, so it cannot be treated as a git repository. This fires before the finer 'not a git repository' classification when the .git discovery itself comes up empty.
Source
Thrown at crates/gitbutler-project/src/project.rs:331
/// Try to get the `Project`, returning an error if it was not added.
pub fn try_project(self) -> anyhow::Result<Project> {
match self {
AddProjectOutcome::Added(p) => Ok(p),
AddProjectOutcome::AlreadyExists(_) => Err(anyhow::anyhow!("project already exists")),
AddProjectOutcome::PathNotFound => Err(anyhow::anyhow!("project path not found")),
AddProjectOutcome::NotADirectory => {
Err(anyhow::anyhow!("project path is not a directory"))
}
AddProjectOutcome::BareRepository => {
Err(anyhow::anyhow!("bare repositories are not supported"))
}
AddProjectOutcome::NonMainWorktree => {
Err(anyhow::anyhow!("non-main worktrees are not supported"))
}
AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!("no workdir found for repository")),
AddProjectOutcome::NoDotGitDirectory => {
Err(anyhow::anyhow!("no .git directory found in repository"))
}
AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(
"unsupported repository reference format: reftable"
)),
AddProjectOutcome::NotAGitRepository(msg) => {
Err(anyhow::anyhow!("not a git repository: {msg}"))
}
}
}
}
View on GitHub (pinned to caf1f223d3)
Solutions
- Run `git init` (or clone) so a .git exists, then add the project
- Pass the repository root that actually contains .git, not a subdirectory
- If .git was accidentally removed, restore it (backup, or re-clone and copy work over) before onboarding
Example fix
// before
let project = add_project(&path, ...).try_project()?; // no .git -> rejected
// after: require a .git entry before adding
if !path.join(".git").exists() {
anyhow::bail!("no .git at {} — run `git init` or pass the repository root", path.display());
}
let project = add_project(&path, ...).try_project()?; Defensive patterns
Strategy: validation
Validate before calling
if !path.join(".git").exists() {
anyhow::bail!("no .git at {} — run `git init` or pass the repository root", path.display());
}
let project = add_project(&path, ...).try_project()?; Type guard
fn looks_like_git_repo_root(p: &Path) -> bool {
p.join(".git").exists() // directory (normal) or gitdir: file (worktree)
} Try / catch
match add_project(&path, ...) {
AddProjectOutcome::NoDotGitDirectory => prompt_to_init_or_clone(&path),
outcome => outcome.try_project(),
} Prevention
- Require a .git entry before add_project
- Pass the repository root, not a subfolder that happens to be inside a repo
- If users select subfolders, walk upward to find the containing .git before adding
When it happens
Trigger: add_project on a plain folder never used with git; a directory whose .git was deleted or renamed; subdirectories of a repo passed without discovery from the root; .dotfile filtering/hidden-file settings hiding .git from discovery.
Common situations: Selecting a random project folder or an extracted tarball without .git; users who deleted .git to 'reset' the repo; picking a subfolder while expecting automatic upward discovery.
Related errors
- project path not found
- project path is not a directory
- bare repositories are not supported
- non-main worktrees are not supported
- no workdir found for repository
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/bc28f917dac6db63.
Report an issue: GitHub.