{"record":{"id":"f94c654ecb77f3b6","repo":"gitbutlerapp/gitbutler","slug":"cannot-merge-branch-name-it-shares-no-history-with-fetch","errorCode":null,"errorMessage":"Cannot merge {branch_name}: it shares no history with {fetch_remote_name}/{target_branch_name}","messagePattern":"Cannot merge (.+?): it shares no history with (.+?)/(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/land/merge.rs","lineNumber":52,"sourceCode":"    no_ff: bool,\n) -> anyhow::Result<LandOutcome> {\n    let feature_ref_name = format!(\"refs/heads/{branch_name}\");\n    let feature_oid = repo\n        .try_find_reference(&feature_ref_name)?\n        .ok_or_else(|| anyhow::anyhow!(\"Branch {branch_name} not found\"))?\n        .into_fully_peeled_id()?\n        .detach();\n\n    let target_ref_name = format!(\"refs/remotes/{fetch_remote_name}/{target_branch_name}\");\n    let target_oid = repo\n        .try_find_reference(&target_ref_name)?\n        .ok_or_else(|| anyhow::anyhow!(\"Target branch {target_ref_name} not found\"))?\n        .into_fully_peeled_id()?\n        .detach();\n\n    // No common ancestor: refuse rather than merge two unrelated histories onto the target.\n    let Some(merge_base) = super::merge_base_opt(repo, feature_oid, target_oid)? else {\n        bail!(\n            \"Cannot merge {branch_name}: it shares no history with {fetch_remote_name}/{target_branch_name}\"\n        );\n    };\n\n    if merge_base == feature_oid {\n        return Ok(LandOutcome::AlreadyIntegrated);\n    }\n    if merge_base == target_oid && !no_ff {\n        return Ok(LandOutcome::FastForward {\n            feature_oid,\n            target_oid,\n        });\n    }\n\n    // Diverged (or `--no-ff`): build a real merge commit. Use GitButler's canonical tree-merge\n    // options (rename tracking on, fail-fast) so a rename+edit can't silently mismerge, and sign\n    // the commit per config so it survives signed-branch protection on the target.\n    // Use each commit's resolved tree as its side of the 3-way merge. For an ordinary","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/land/merge.rs#L34-L70","documentation":"Landing a branch merges it into the remote target branch. Git cannot merge two unrelated histories (no common merge-base ancestor). Rather than producing a broken merge, `decide_land_outcome` refuses with this error.","triggerScenarios":"Calling `but merge <branch>` where the feature branch and `{fetch_remote}/{target_branch}` share no merge-base — typically when the branch was created from an orphan/unrelated history or the target was re-created from scratch.","commonSituations":"Target branch force-recreated without history; branch created in a fresh repo with no shared root; repo seeded from unrelated template histories.","solutions":["Rebase the branch onto the target to establish common history, or cherry-pick its commits onto a branch created from the target","Recreate the branch from the current target branch (`git switch -c fix origin/main`) and reapply changes","Verify you are merging into the intended target branch — pointing at the wrong remote branch can look like unrelated history"],"exampleFix":"# before\nbut merge orphan-branch\n# error: shares no history with origin/main\n\n# after\ngit switch -c orphan-branch-rebased origin/main\ngit cherry-pick <commits-from-orphan-branch>\nbut merge orphan-branch-rebased","handlingStrategy":"validation","validationCode":"let base = repo.merge_base(feature_oid, target_oid);\nif base.is_err() {\n    println!(\"branch shares no history with target; rebase or recreate branch\");\n    return Ok(());\n}","typeGuard":null,"tryCatchPattern":"match land_result {\n    Err(e) if e.to_string().contains(\"shares no history\") => {\n        recreate_branch_from_target();\n    }\n    other => other?,\n}","preventionTips":["Create branches from the current target branch, never from orphan roots","Avoid force-recreating the target branch from scratch without migrating history","Verify the target remote/branch name resolves to the intended upstream before landing"],"tags":["git","merge","unrelated-histories","landing"],"backgroundTag":"unsupported-operation","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"}