{"record":{"id":"957a5a935242d081","repo":"GitoxideLabs/gitoxide","slug":"the-head-pin-must-point-to-a-local-branch","errorCode":null,"errorMessage":"the HEAD pin must point to a local branch","messagePattern":"the HEAD pin must point to a local branch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/time_travel.rs","lineNumber":498,"sourceCode":"        } else {\n            notice = format!(\"{notice}; saved {}\", pin_label(&provisional));\n        }\n    }\n    Ok((Some(notice), ref_changes))\n}\n\nfn remembered_branch(repository: &gix::Repository) -> Result<RememberedBranch> {\n    let pin = history::all_pins(repository)?\n        .into_iter()\n        .find(history::Pin::is_head)\n        .context(\"attaching requires a valid HEAD pin\")?;\n    let branch = pin\n        .target\n        .try_name()\n        .context(\"the HEAD pin must point to a local branch\")?\n        .to_owned();\n    if !branch.as_bstr().starts_with(b\"refs/heads/\") {\n        anyhow::bail!(\"the HEAD pin must point to a local branch\");\n    }\n    Ok(RememberedBranch {\n        branch,\n        branch_tip: pin.id,\n    })\n}\n\nfn validate_attach(repository: &gix::Repository, head_id: ObjectId, remembered: &RememberedBranch) -> Result<()> {\n    let head = repository.head().context(\"could not read HEAD before attaching\")?;\n    if !head.is_detached() || head.id().map(gix::Id::detach) != Some(head_id) {\n        anyhow::bail!(\"HEAD changed while preparing to attach\");\n    }\n    drop(head);\n    let pin = history::all_pins(repository)?\n        .into_iter()\n        .find(history::Pin::is_head)\n        .context(\"the HEAD pin disappeared while preparing to attach\")?;\n    if pin.target.try_name() != Some(remembered.branch.as_ref()) || pin.id != remembered.branch_tip {","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/time_travel.rs#L480-L516","documentation":"The remembered HEAD pin's target is not a symbolic reference to a local branch: either `try_name()` returned None (detached HEAD) or the name does not start with `refs/heads/`. Attaching time-travel state requires HEAD to be anchored to a local branch so it can be re-attached later. The library throws this when snapshotting/remembering the current branch.","triggerScenarios":"Calling remembered_branch (via attach_reporting) while HEAD is detached, or while HEAD points at something other than a local branch (e.g. `refs/remotes/origin/main`, a tag, or another pseudo-ref).","commonSituations":"Operating in a repo checked out at a bare commit (detached HEAD, e.g. after `git checkout <sha>` or CI checkouts); HEAD pointing to a remote-tracking branch; a pin captured on a tag.","solutions":["Check out a local branch first (`git checkout -b <name>` to create one from the current commit).","Ensure HEAD resolves to a `refs/heads/*` ref before starting the time-travel/attach flow.","If on a remote-tracking state, create a local branch tracking it."],"exampleFix":"// before (detached HEAD)\n$ git checkout 1a2b3c4  # attach fails\n// after\n$ git checkout -b work  # local branch, attach succeeds","handlingStrategy":"validation","validationCode":"let head = repo.head()?;\nlet is_local_branch = !head.is_detached()\n    && head.referent_name().map(|n| n.as_bstr().starts_with(b\"refs/heads/\")).unwrap_or(false);\nif !is_local_branch { return Err(anyhow!(\"must be on a local branch\")); }","typeGuard":"fn on_local_branch(head: &gix::reference::Reference<'_>) -> bool {\n    !head.is_detached()\n        && head\n            .referent_name()\n            .map(|n| n.as_bstr().starts_with(b\"refs/heads/\"))\n            .unwrap_or(false)\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"must point to a local branch\") => {\n        eprintln!(\"detached HEAD; create/checkout a local branch first\");\n    }\n    other => other?,\n}","preventionTips":["Never run the flow from a detached-HEAD checkout (common in CI).","Create a local branch when starting from a remote-tracking or tag state.","Assert HEAD is symbolic to refs/heads/* at workflow start."],"tags":["git","detached-head","branch","precondition"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}