{"record":{"id":"b0cf9ba5cf429059","repo":"gitbutlerapp/gitbutler","slug":"cannot-uncommit-hunks-that-would-result-in-merge-c","errorCode":null,"errorMessage":"Cannot uncommit hunks that would result in merge conflicts","messagePattern":"Cannot uncommit hunks that would result in merge conflicts","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/squash.rs","lineNumber":1454,"sourceCode":"                } => SquashOutcome::UncommitBranch {\n                    branch_names: source_branches,\n                },\n            };\n            Ok((outcome, Some(ws)))\n        }\n        ExecutableSquashOperation::UncommitHunks { source, changes } => {\n            {\n                let but_api::commit::types::MoveChangesResult { workspace } =\n                    but_api::commit::uncommit::commit_uncommit_changes_only_with_perm(\n                        ctx,\n                        source.commit_id,\n                        changes.clone(),\n                        None,\n                        DryRun::Yes,\n                        perm,\n                    )?;\n\n                anyhow::ensure!(\n                    !workspace.is_conflicted(),\n                    \"Cannot uncommit hunks that would result in merge conflicts\"\n                );\n            }\n\n            let but_api::commit::types::MoveChangesResult { workspace: _ } =\n                but_api::commit::uncommit::commit_uncommit_changes_with_perm(\n                    ctx,\n                    source.commit_id,\n                    changes,\n                    None,\n                    DryRun::No,\n                    perm,\n                )?;\n\n            Ok((SquashOutcome::UncommitHunk { source }, None))\n        }\n    }","sourceCodeStart":1436,"sourceCodeEnd":1472,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/squash.rs#L1436-L1472","documentation":"Hunk-level variant of the uncommit conflict guard: selected hunks are simulated via `commit_uncommit_changes_only_with_perm(..., DryRun::Yes)`, and if the simulated workspace reports conflicts the operation aborts before `commit_uncommit_changes_with_perm(..., DryRun::No)` performs the real move. It means the specific hunks you picked collide with other content in the workspace.","triggerScenarios":"Uncommitting an individual hunk that overlaps lines also modified by other hunks kept in the commit, by later commits in the stack, or by existing workspace changes — the dry run ends conflicted.","commonSituations":"Fine-grained hunk splitting inside a commit where later commits edited adjacent/same lines; picking partial hunks while the workspace is dirty in the same file.","solutions":["Select fewer hunks — drop the hunk that overlaps and uncommit the rest","Uncommit the whole commit instead of individual hunks (whole-commit moves avoid intra-commit collisions)","Clean or commit the workspace's overlapping changes in that file first, then retry the hunk selection","Reorder work: ship or uncommit the dependent later commits before extracting the hunk"],"exampleFix":"# before: hunk selection that collides with kept content\nbut squash --uncommit-hunks c3 :1,3\n\n# after: whole-commit uncommit, no hunk overlap\nbut squash --uncommit c3","handlingStrategy":"validation","validationCode":"let but_api::commit::types::MoveChangesResult { workspace, .. } =\n    but_api::commit::uncommit::commit_uncommit_changes_only_with_perm(\n        ctx, commit_id, changes.clone(), None, DryRun::Yes, perm,\n    )?;\nif workspace.is_conflicted() {\n    anyhow::bail!(\"hunk selection would conflict; drop overlapping hunks or uncommit the whole commit\");\n}","typeGuard":"fn dry_run_is_conflicted(workspace: &but_graph::Workspace) -> bool {\n    workspace.is_conflicted()\n}","tryCatchPattern":"match run_uncommit_hunks(ctx, commit_id, changes, perm) {\n    Ok(result) => { /* use result */ }\n    Err(err) if err.to_string().contains(\"hunks that would result in merge conflicts\") => {\n        // retry with fewer hunks or fall back to whole-commit uncommit\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Select fewer hunks when a dry run conflicts; overlap is almost always the cause","Prefer whole-commit uncommit when intra-commit hunk overlaps appear","Commit or stash workspace edits in the same file before extracting hunks"],"tags":["rust","cli","git","uncommit","hunks","merge-conflict","dry-run","workspace"],"backgroundTag":"merge-conflict","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}