{"record":{"id":"00ae759dec88b178","repo":"Hmbown/CodeWhale","slug":"the-pinned-pr-commits-do-not-have-one-available-merge-base","errorCode":null,"errorMessage":"The pinned PR commits do not have one available merge base","messagePattern":"The pinned PR commits do not have one available merge base","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/review_pr.rs","lineNumber":287,"sourceCode":"                let shallow = run(\n                    Program::Git,\n                    &[\"rev-parse\".into(), \"--is-shallow-repository\".into()],\n                )?;\n                if shallow.trim() != \"false\" {\n                    bail!(\"A full Git history is required to establish the PR merge base\");\n                }\n                let base = run(\n                    Program::Git,\n                    &[\n                        \"merge-base\".into(),\n                        \"--all\".into(),\n                        view.base_sha.clone(),\n                        view.head_sha.clone(),\n                    ],\n                )?;\n                let base = base.trim();\n                if !commit_id(base) {\n                    bail!(\"The pinned PR commits do not have one available merge base\");\n                }\n                let diff = run(\n                    Program::Git,\n                    &[\n                        \"diff\".into(),\n                        \"--no-ext-diff\".into(),\n                        \"--no-textconv\".into(),\n                        \"--no-color\".into(),\n                        \"--no-relative\".into(),\n                        \"--full-index\".into(),\n                        \"--find-renames=50%\".into(),\n                        \"--src-prefix=a/\".into(),\n                        \"--dst-prefix=b/\".into(),\n                        \"--ignore-submodules=none\".into(),\n                        \"--submodule=short\".into(),\n                        base.into(),\n                        view.head_sha.clone(),\n                        \"--\".into(),","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/review_pr.rs#L269-L305","documentation":"After the shallow check, diff_with runs `git merge-base --all <base_sha> <head_sha>`. The result must be exactly one full 40-hex commit ID; multiple candidates (criss-cross/ambiguous merge bases) or no candidate mean there is no single well-defined merge base, and the review diff cannot be computed deterministically.","triggerScenarios":"`git merge-base --all` for the pinned PR base/head returns empty (unrelated or missing history — objects not fetched) or more than one commit (criss-cross merges), so the trimmed output fails commit_id().","commonSituations":"Missing remote objects because origin wasn't fully fetched; histories of base and head branches diverged with multiple equally best ancestors; base SHA references a commit absent from the local clone; force-pushed base leaving orphaned pins.","solutions":["Fetch the missing objects: `git fetch origin <base_sha> <head_sha>` (or `git fetch origin '+refs/*:refs/remotes/origin/*' --prune --no-tags`), then retry","If merge-base --all lists multiple commits, inspect `git log --graph` for criss-cross merges and confirm the PR's current base/head on GitHub; re-pin to the latest SHAs by re-running the review","Confirm both SHAs exist locally with `git cat-file -e <sha>^{commit}` before retrying"],"exampleFix":"// before: ambiguous result silently used\nlet base = base.trim();\n// after: require exactly one full commit id\nlet base = base.trim();\nif !commit_id(base) {\n    bail!(\"The pinned PR commits do not have one available merge base\");\n}","handlingStrategy":"validation","validationCode":"// confirm exactly one merge base and full objects exist\nlet out = Command::new(\"git\").args([\"merge-base\",\"--all\",&base,&head]).output()?;\nlet bases: Vec<&str> = String::from_utf8_lossy(&out.stdout).trim().lines().collect();\nassert_eq!(bases.len(), 1, \"expected one merge base, got {}\", bases.len());\nfor sha in [&base, &head, bases[0]] {\n    assert!(Command::new(\"git\").args([\"cat-file\",\"-e\",format!(\"{sha}^{{commit}}\").as_str()]).status()?.success(), \"missing object {sha}\");\n}","typeGuard":null,"tryCatchPattern":"let out = Command::new(\"git\").args([\"merge-base\",\"--all\",&base,&head]).output()?;\nlet n = String::from_utf8_lossy(&out.stdout).trim().lines().count();\nif n != 1 { git_fetch_missing(&base, &head)?; } // then retry the review","preventionTips":["Fetch both pinned SHAs explicitly (`git fetch origin <sha>`) before diffing","Keep the clone unshallow and up to date","Investigate criss-cross merges if merge-base --all ever returns multiple results"],"tags":["git","merge-base","ambiguous-history","external-command"],"backgroundTag":"git-command-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}