gitbutlerapp/gitbutler · error · anyhow::Error

Moving branches in non-managed workspaces is not supported

Error message

Moving branches in non-managed workspaces is not supported

What it means

`tear_off_branch` bails when `workspace.kind` is `AdHoc` — the repository is being used without a managed GitButler workspace (plain git usage mode). Moving branches between stacks is only defined for managed workspaces, where stacks and the workspace commit exist.

Source

Thrown at crates/but-workspace/src/branch/move_branch.rs:81

        let successful_rebase = editor.rebase()?;
        let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;
        let mut editor = successful_rebase.into_editor();
        let Some(source) = workspace.find_segment_and_stack_by_refname(subject_branch_name) else {
            bail!(
                "Couldn't find branch to move in workspace with reference name: {subject_branch_name}"
            );
        };

        // We're currently stopping the move branch operations imperatively at this stage, in order to
        // reduce the scope of this first iteration of moving the branches.
        // TODO: Enable and test that we can move branches in any kind of workspace.
        match &workspace.kind {
            WorkspaceKind::Managed { .. } => {}
            WorkspaceKind::ManagedMissingWorkspaceCommit { .. } => {
                bail!("Moving branches currently need a workspace commit")
            }
            WorkspaceKind::AdHoc => {
                bail!("Moving branches in non-managed workspaces is not supported");
            }
        };

        let mut ws_meta = workspace.metadata.clone();

        let (source_stack, subject_segment) = source;

        if source_stack.segments.len() == 1 {
            // There's only one branch in the source stack. Nothing to do.
            return Ok(Outcome {
                rebase: editor.rebase()?,
                ws_meta,
                new_tip: None,
                branch_stack_order: None,
            });
        }

        let Some(workspace_head) = workspace.tip_commit().map(|commit| commit.id) else {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Guard the call: only offer branch move when `matches!(workspace.kind, WorkspaceKind::Managed { .. })`.
  2. If the user wants managed features, create/adopt a workspace first, then retry.
Defensive patterns

Strategy: validation

Validate before calling

if matches!(workspace.kind, but_graph::WorkspaceKind::AdHoc) {
    anyhow::bail!("repo is used ad-hoc (no managed workspace); create/adopt a workspace before moving branches");
}

Type guard

fn workspace_supports_branch_move(kind: &but_graph::WorkspaceKind) -> bool {
    matches!(kind, but_graph::WorkspaceKind::Managed { .. })
}

Try / catch

if let Err(err) = move_branch::tear_off_branch(editor, &branch, None) {
    if err.to_string().contains("non-managed workspaces") {
        // offer to set up a managed workspace, or hide the feature for this repo
    }
}

Prevention

When it happens

Trigger: Calling move-branch on a repo that GitButler tracks ad-hoc (no workspace commit/stacks created), e.g. a freshly opened project where the user never created a managed workspace, or after abandoning the workspace.

Common situations: Integrating the move API into a tool that runs against arbitrary repos without checking adoption state; users who opened a repo but never set up GitButler branching.

Related errors


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