{"record":{"id":"1f992569eb6f50f1","repo":"gitbutlerapp/gitbutler","slug":"cannot-land-branch-it-would-publish-confli","errorCode":null,"errorMessage":"Cannot land `{branch}`: it would publish {} conflicted commit{} ({}). Resolve them first with `but resolve <commit>`.","messagePattern":"Cannot land `(.+?)`: it would publish (.+?) conflicted commit(.+?) \\((.+?)\\)\\. Resolve them first with `but resolve <commit>`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/land/mod.rs","lineNumber":445,"sourceCode":"            bail!(\n                \"Refusing to land `{branch}`: {} commit(s) on unnamed segment(s) below it would \\\n                 also be published to {target_display}. Pass --whole-stack to land `{branch}` \\\n                 together with everything below it.\",\n                scan.commits_below,\n            );\n        }\n        bail!(\n            \"Refusing to land `{branch}`: it is stacked on top of {} other segment(s) ({}) \\\n             whose commits would also be published to {target_display}. Land the bottom segment \\\n             `{}`, or pass --whole-stack to land `{branch}` together with everything below it.\",\n            scan.lower_segments.len(),\n            scan.lower_segments.join(\", \"),\n            scan.lower_segments.last().expect(\"non-empty checked above\"),\n        );\n    }\n\n    if !scan.conflicted.is_empty() {\n        bail!(\n            \"Cannot land `{branch}`: it would publish {} conflicted commit{} ({}). \\\n             Resolve them first with `but resolve <commit>`.\",\n            scan.conflicted.len(),\n            if scan.conflicted.len() == 1 { \"\" } else { \"s\" },\n            scan.conflicted.join(\", \"),\n        );\n    }\n    Ok(scan.lower_segments)\n}\n\n/// Fetch the target's fetch remote and record the outcome on the project, mirroring the\n/// bookkeeping `fetch_from_remotes` performs so `last_fetched` and auto-fetch scheduling stay\n/// accurate for targeted fetches too.\nfn fetch_target_remote(ctx: &Context, remote: &str) -> anyhow::Result<()> {\n    use anyhow::Context as _;\n\n    let result = ctx.fetch(remote, Some(\"land\".to_string()));\n    let timestamp = std::time::SystemTime::now();","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/land/mod.rs#L427-L463","documentation":"`validate_branch_landing` refuses to land a branch whose publish set contains conflicted commits. Pushing or merging conflicted commits would produce a broken or rejected integration on the target, so GitButler blocks the land and lists the conflicted commit IDs, directing the developer to resolve them with `but resolve <commit>` first.","triggerScenarios":"Calling `branch_land` when `scan.conflicted` is non-empty — one or more commits in the segment(s) that would be published are in a conflicted state (e.g. after a rebase or pull left unresolved conflicts).","commonSituations":"After `but pull` / `but rebase` introduced conflicts that were not fully resolved; applying upstream changes that conflict with local commits; returning to a workspace after an interrupted conflict-resolution session.","solutions":["Run `but resolve <commit>` for each listed commit and resolve the conflicts, then retry the land.","Use the GitButler UI/TUI conflict-resolution flow to clear all conflicted commits.","Remove or rework the conflicted commits if they are no longer needed."],"exampleFix":"// before\nbut land feature-x   // refused: would publish 2 conflicted commits (abc123, def456)\n// after\nbut resolve abc123\nbut resolve def456\nbut land feature-x","handlingStrategy":"validation","validationCode":"// check for conflicted commits in the publish set before landing\nconst ws = await api.workspaceState();\nconst conflicted = ws.stacks.flatMap(s => s.commits).filter(c => c.conflicted);\nif (conflicted.length) throw new Error(`Resolve ${conflicted.map(c => c.id).join(', ')} before landing`);","typeGuard":"function hasConflictedCommits(commits) {\n  return commits.some(c => c.conflicted === true);\n}","tryCatchPattern":"try {\n  await api.land(branch);\n} catch (e) {\n  const ids = String(e).match(/\\(([a-f0-9,\\s]+)\\)/)?.[1]?.split(',').map(s => s.trim());\n  if (ids) {\n    for (const id of ids) await api.resolve(id);\n    await api.land(branch);\n  } else throw e;\n}","preventionTips":["Run conflict resolution (`but resolve`) right after any pull/rebase that reports conflicts.","Check `but status` for conflicted commits before every land.","Avoid leaving a workspace session with unresolved conflicts pending."],"tags":["git","merge-conflicts","validation","stacked-branches"],"backgroundTag":"invalid-state-transition","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}