gitbutlerapp/gitbutler · error · anyhow::Error

Cannot move branch {subject_branch_name} onto itself

Error message

Cannot move branch {subject_branch_name} onto itself

What it means

move_branch refuses when the subject and target reference names are identical, because moving a branch onto itself is a no-op at best and a graph-corrupting cycle at worst. It is a pure argument-validation error raised before any rebase or traversal runs, so no repository state is touched.

Source

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

    /// `editor` is assumed to have been generated from the given `workspace`
    /// and therefore aligned.
    ///
    /// `workspace` - Used for getting the surrounding context of the branch being moved.
    ///     In the future, we should not rely on the projection and do it fully on the graph.
    ///
    /// `subject_branch_name` is the full reference name of the branch to move.
    ///
    /// `target_branch_name` is the full reference name of the branch to move the subject
    /// branch on top of.
    ///
    /// Returns an [outcome](Outcome) for potential materialisation.
    pub fn move_branch<'ws, 'meta, M: RefMetadata>(
        editor: Editor<'ws, 'meta, M>,
        subject_branch_name: &FullNameRef,
        target_branch_name: &FullNameRef,
    ) -> anyhow::Result<Outcome<'ws, 'meta, M>> {
        if subject_branch_name == target_branch_name {
            bail!("Cannot move branch {subject_branch_name} onto itself");
        }

        let successful_rebase = editor.rebase()?;
        let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;

        let (source, destination) =
            retrieve_branches_and_containers(&workspace, subject_branch_name, target_branch_name)?;

        // Each kind of workspace has a very different notion of what "moving a branch" means, so we
        // dispatch into a dedicated handler for each one.
        match &workspace.kind {
            WorkspaceKind::AdHoc => move_branch_in_single_branch_mode(
                successful_rebase,
                workspace,
                source,
                destination,
                subject_branch_name,
                target_branch_name,

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Skip the call when subject_branch_name == target_branch_name (treat it as a no-op success in the UI layer).
  2. Fix the caller so the drop target is a different branch than the dragged one.
  3. If names come from user input, validate they differ before resolving them to full ref names.

Example fix

// before
move_branch(editor, subject_branch_name, target_branch_name)?;

// after
if subject_branch_name == target_branch_name {
    return Ok(outcome_noop()); // nothing to move
}
move_branch(editor, subject_branch_name, target_branch_name)?;
Defensive patterns

Strategy: validation

Validate before calling

if subject_branch_name == target_branch_name {
    // no-op: treat as success without calling the API
    return Ok(default_outcome());
}

Prevention

When it happens

Trigger: Calling but_workspace::branch::move_branch(editor, name, name) with the same FullNameRef for subject and target, e.g. because a UI passed the dragged row as both source and destination.

Common situations: Drag-and-drop UI bugs where a branch is dropped onto itself; refactored callers that accidentally reuse one variable for both parameters; fuzzy branch-name matching that resolves two different user inputs to the same full ref name.

Related errors


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