{"record":{"id":"cb2604d6e38da547","repo":"gitbutlerapp/gitbutler","slug":"cannot-move-branch-subject-branch-name-onto-itse","errorCode":null,"errorMessage":"Cannot move branch {subject_branch_name} onto itself","messagePattern":"Cannot move branch (.+?) onto itself","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/branch/move_branch.rs","lineNumber":186,"sourceCode":"    /// `editor` is assumed to have been generated from the given `workspace`\n    /// and therefore aligned.\n    ///\n    /// `workspace` - Used for getting the surrounding context of the branch being moved.\n    ///     In the future, we should not rely on the projection and do it fully on the graph.\n    ///\n    /// `subject_branch_name` is the full reference name of the branch to move.\n    ///\n    /// `target_branch_name` is the full reference name of the branch to move the subject\n    /// branch on top of.\n    ///\n    /// Returns an [outcome](Outcome) for potential materialisation.\n    pub fn move_branch<'ws, 'meta, M: RefMetadata>(\n        editor: Editor<'ws, 'meta, M>,\n        subject_branch_name: &FullNameRef,\n        target_branch_name: &FullNameRef,\n    ) -> anyhow::Result<Outcome<'ws, 'meta, M>> {\n        if subject_branch_name == target_branch_name {\n            bail!(\"Cannot move branch {subject_branch_name} onto itself\");\n        }\n\n        let successful_rebase = editor.rebase()?;\n        let workspace = successful_rebase.overlayed_graph()?.into_workspace()?;\n\n        let (source, destination) =\n            retrieve_branches_and_containers(&workspace, subject_branch_name, target_branch_name)?;\n\n        // Each kind of workspace has a very different notion of what \"moving a branch\" means, so we\n        // dispatch into a dedicated handler for each one.\n        match &workspace.kind {\n            WorkspaceKind::AdHoc => move_branch_in_single_branch_mode(\n                successful_rebase,\n                workspace,\n                source,\n                destination,\n                subject_branch_name,\n                target_branch_name,","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/branch/move_branch.rs#L168-L204","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Skip the call when subject_branch_name == target_branch_name (treat it as a no-op success in the UI layer).","Fix the caller so the drop target is a different branch than the dragged one.","If names come from user input, validate they differ before resolving them to full ref names."],"exampleFix":"// before\nmove_branch(editor, subject_branch_name, target_branch_name)?;\n\n// after\nif subject_branch_name == target_branch_name {\n    return Ok(outcome_noop()); // nothing to move\n}\nmove_branch(editor, subject_branch_name, target_branch_name)?;","handlingStrategy":"validation","validationCode":"if subject_branch_name == target_branch_name {\n    // no-op: treat as success without calling the API\n    return Ok(default_outcome());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compare subject and target ref names before every move call.","In drag-and-drop UIs, ignore drops where source row == target row.","Log both names when refusing, to catch caller mapping bugs early."],"tags":["gitbutler","move-branch","validation","rust"],"backgroundTag":"self-referential-operation","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}