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
- 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.
- As a fallback, recreate the workspace (unadopt/re-adopt) so kind returns to `Managed`.
- 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
- Gate the move-branch action on workspace.kind == Managed in the UI.
- After losing the workspace commit (manual ref deletion, gc), repair before using stack operations.
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
- Moving branches in non-managed workspaces is not supported
- Couldn't find workspace head.
- Couldn't find branch to move in workspace with reference nam
- Failed to create blank commit in stack: {stack_id:?}
- Failed to create blank commit in leftmost stack
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/176883324a12c632.
Report an issue: GitHub.