gitbutlerapp/gitbutler · error

Refusing to work on workspace whose workspace commit isn't a

Error message

Refusing to work on workspace whose workspace commit isn't at the top

What it means

unapply refuses to operate when WorkspaceExt::has_workspace_commit_in_ancestry() is true, i.e. a workspace merge commit exists buried in the workspace's history while the workspace ref does not point directly at it (never true for healthy managed workspaces). Commits on top of the workspace commit would be lost or misattributed by an unapply in that state, so the operation aborts before touching refs.

Source

Thrown at crates/but-workspace/src/branch/unapply.rs:205

    #[tracing::instrument(skip(workspace, repo, meta), err(Debug))]
    pub fn unapply<'ws>(
        branch: &FullNameRef,
        workspace: &'ws but_graph::Workspace,
        repo: &gix::Repository,
        meta: &mut impl RefMetadata,
        Options {
            workspace_disposition,
        }: Options,
    ) -> anyhow::Result<Outcome<'ws>> {
        let ws = workspace;
        let mut branch_ref = try_find_validated_ref(repo, branch, "unapply")?;
        let branch_commit_id = branch_ref
            .as_mut()
            .map(|reference| reference.peel_to_id().map(|id| id.detach()))
            .transpose()?;

        if ws.has_workspace_commit_in_ancestry(repo) {
            bail!("Refusing to work on workspace whose workspace commit isn't at the top");
        }

        let workspace_ref_name = ws.ref_name().map(ToOwned::to_owned);
        if matches!(ws.kind, but_graph::workspace::WorkspaceKind::AdHoc)
            && branch_ref
                .as_ref()
                .zip(workspace_ref_name.as_ref())
                .is_some_and(|(to_unapply, workspace_ref_name)| {
                    to_unapply.name() == workspace_ref_name.as_ref()
                })
        {
            bail!(
                "Cannot unapply branch '{branch}' from an ad-hoc workspace because the workspace cannot be empty",
                branch = branch.shorten()
            );
        }

        if let Some(workspace_ref_name) = workspace_ref_name.as_ref()

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Undo or move the commits that sit on top of the workspace commit (git reset / GitButler undo), so the workspace commit is at the top again.
  2. Open the project in GitButler and let it reconcile the workspace state before unapplying.
  3. If the buried workspace commit is stale, rebuild the workspace on a clean base.

Example fix

// before
let outcome = but_workspace::branch::unapply(repo, meta, ws, branch, Options::default())?;

// after
use but_workspace::ref_info::WorkspaceExt as _;
ensure!(!ws.has_workspace_commit_in_ancestry(repo), "commits sit on top of the workspace commit; move them first");
let outcome = but_workspace::branch::unapply(repo, meta, ws, branch, Options::default())?;
Defensive patterns

Strategy: validation

Validate before calling

use but_workspace::ref_info::WorkspaceExt as _;
if ws.has_workspace_commit_in_ancestry(repo) {
    // commits sit on top of the workspace commit; refuse early with guidance
    return Err(anyhow!("move commits off the workspace commit before unapplying"));
}

Type guard

fn workspace_commit_is_at_top(ws: &but_graph::Workspace, repo: &gix::Repository) -> bool {
    use but_workspace::ref_info::WorkspaceExt as _;
    !ws.has_workspace_commit_in_ancestry(repo)
}

Try / catch

match unapply(repo, meta, &ws, branch, opts) {
    Err(err) if err.to_string().contains("isn't at the top") => {
        ui::error("Undo commits made on top of the workspace, then retry");
        Ok(default_outcome())
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling branch::unapply on an ad-hoc/legacy workspace where a workspace merge commit exists in the ancestry below newer commits — e.g. the user committed on top of the workspace merge commit outside GitButler.

Common situations: User runs git commit while on a GitButler workspace ref; interrupted GitButler sync left an old workspace commit in history; worktrees shared with other tools that commit directly.

Related errors


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