gitbutlerapp/gitbutler · error
bare repositories are not supported
Error message
bare repositories are not supported
What it means
AddProjectOutcome::BareRepository mapped through try_project: the path hosts a bare repository (no working tree). GitButler's virtual branches operate on a worktree, so bare repos (typically created with git clone --bare / git init --bare) are rejected at add time.
Source
Thrown at crates/gitbutler-project/src/project.rs:324
/// Panics if it was not.
pub fn unwrap_project(self) -> Project {
match self {
AddProjectOutcome::Added(p) => p,
_ => panic!("called `AddProjectOutcome::unwrap_project()` on a non-project outcome"),
}
}
/// 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
- Add a non-bare clone/worktree instead: `git clone <bare-repo> <worktree>` and add that directory
- Verify before adding: check for core.bare=true in the repo config or the absence of a work tree
- If the bare repo is only a mirror, create a working clone elsewhere for daily use
Example fix
// before
let project = add_project(&path, ...).try_project()?; // bare repo -> rejected
// after: pre-detect bare repos and guide the user
fn is_bare(path: &Path) -> bool {
std::process::Command::new("git")
.args(["-C", path.to_str().unwrap(), "rev-parse", "--is-bare-repository"])
.output().map(|o| o.stdout.trim() == b"true").unwrap_or(false)
}
if is_bare(&path) {
anyhow::bail!("bare repositories are unsupported — clone it first: git clone {path:?} worktree");
} Defensive patterns
Strategy: validation
Validate before calling
fn is_bare_repo(path: &Path) -> bool {
std::process::Command::new("git")
.args(["-C", &path.to_string_lossy(), "rev-parse", "--is-bare-repository"])
.output()
.map(|o| o.stdout.trim() == b"true")
.unwrap_or(false)
}
if is_bare_repo(&path) {
anyhow::bail!("bare repository — clone it to a worktree first");
} Try / catch
match add_project(&path, ...) {
AddProjectOutcome::BareRepository => guide_user_to_clone_worktree(&path),
outcome => outcome.try_project(),
} Prevention
- Screen candidate paths with `git rev-parse --is-bare-repository` before onboarding
- Only onboard standard clones (folder containing .git), never mirror/bare directories
- In pickers, show a clear message when a bare repo is selected so users know to clone instead
When it happens
Trigger: add_project on a directory created with `git init --bare` or `git clone --bare`; a repo whose config has core.bare=true; server-style hosting dirs (git daemon, custom Git servers).
Common situations: Trying to onboard a bare mirror used for internal hosting; confusing the bare repo dir with its non-bare clone; tooling that defaults to bare clones for mirrors.
Related errors
- non-main worktrees are not supported
- no workdir found for repository
- no .git directory found in repository
- not a git repository: {msg}
- Invalid message format
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/8a2a99927f2ea7d8.
Report an issue: GitHub.