gitbutlerapp/gitbutler · error · anyhow::Error

Moving branches currently need a workspace commit

Error message

Moving branches currently need a workspace commit

What it means

`tear_off_branch` only supports workspaces of kind `Managed`; when `workspace.kind` is `ManagedMissingWorkspaceCommit` (the workspace commit is missing — e.g. the workspace ref/commit was deleted or lost but managed metadata remains) it bails with this message. It is an explicit first-iteration scope limit (see the TODO in the source) rather than a corruption error.

Source

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

        subject_branch_name: &FullNameRef,
        stack_id_override: Option<StackId>,
    ) -> anyhow::Result<Outcome<'ws, 'meta, M>> {
        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,
            });

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Restore or recreate the workspace commit (re-open the project so GitButler can re-establish the workspace, or use its repair/recovery flow), then retry the move.
  2. As a fallback, recreate the workspace (unadopt/re-adopt) so kind returns to `Managed`.
  3. Check `workspace.kind` before calling move-branch and disable the UI action for this state.
Defensive patterns

Strategy: validation

Validate before calling

if !matches!(workspace.kind, but_graph::WorkspaceKind::Managed { .. }) {
    anyhow::bail!("branch move requires a healthy managed workspace (current kind: {:?}); repair the workspace commit first", workspace.kind);
}

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("need a workspace commit") {
        // route user to workspace repair / re-adoption flow
    }
}

Prevention

When it happens

Trigger: Invoking move-branch in a repository whose workspace lost its workspace commit: the `refs/namespace` workspace ref or workspace commit object was removed (manual cleanup, partial clone, interrupted operation) while stack metadata still classifies it as managed.

Common situations: After a failed/interrupted workspace operation, `git gc` pruning, users deleting GitButler refs by hand, or version migrations that drop the workspace commit. The app otherwise may look usable, but branch move refuses.

Related errors


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