{"record":{"id":"125897bdcfce5238","repo":"GitoxideLabs/gitoxide","slug":"detached-head-or-one-of-its-descendants-must-be-pi","errorCode":null,"errorMessage":"detached HEAD or one of its descendants must be pinned before travelling into the past or sideways","messagePattern":"detached HEAD or one of its descendants must be pinned before travelling into the past or sideways","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/command/travel.rs","lineNumber":85,"sourceCode":"        _ => anyhow::bail!(\"exactly one time-travel destination is required\"),\n    };\n    if selected == head_id {\n        println!(\"already at {}\", crate::change_id::display(&repository, selected, 7)?);\n        return Ok(());\n    }\n\n    let revisions = vec![OsString::from(\"HEAD\"), OsString::from(selected.to_string())];\n    let graph = match resolved_graph {\n        Some(graph) => graph,\n        None => crate::edit::loaded_view_graph_with(&repository, &revisions)?,\n    };\n    let forward = graph.is_ancestor(head_id, selected);\n    if detached && !forward {\n        let source_is_pinned = crate::history::all_pins(&repository)?\n            .into_iter()\n            .any(|pin| graph.is_ancestor(head_id, pin.id));\n        if !source_is_pinned {\n            anyhow::bail!(\n                \"detached HEAD or one of its descendants must be pinned before travelling into the past or sideways\"\n            );\n        }\n    }\n\n    let reviews = crate::history::all_reviews(&repository)?\n        .into_iter()\n        .map(|review| review.id)\n        .collect::<Vec<_>>();\n    let repository_path = repository.git_dir().to_owned();\n    let bare = repository.is_bare();\n    drop(repository);\n    match crate::edit::time_travel::perform(&repository_path, bare, selected, &graph, &reviews, &[], false)? {\n        crate::edit::time_travel::Perform::Complete {\n            notice,\n            selected,\n            ref_rewrites,\n            ref_changes,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/command/travel.rs#L67-L103","documentation":"Travelling into the past or sideways from a detached HEAD rewrites what HEAD points at; without a pin covering detached HEAD or one of its descendants, the previous position could become unreachable. run() refuses the move unless the source is pinned (head_id is an ancestor of some pin).","triggerScenarios":"Detached HEAD state + travel to a non-descendant destination (forward == false) while no pin in all_pins() has head_id as an ancestor.","commonSituations":"Browsing history in detached state then jumping to an older commit; pins never created in a fresh clone; sideways moves between branches while detached.","solutions":["Create a pin covering HEAD: `tix pin HEAD` (or pin a descendant), then retry the travel","Attach HEAD to a branch (`git switch <branch>` / checkout) so the position is retained by the ref","Travel only to descendants while detached, which is always allowed"],"exampleFix":"// before\ntix travel HEAD~3        # detached, unpinned\n// after\ntix pin HEAD\ntix travel HEAD~3","handlingStrategy":"validation","validationCode":"let detached = repo.head_detached()?;\nlet forward = graph.is_ancestor(head_id, selected);\nif detached && !forward {\n    let pinned = crate::history::all_pins(&repo)?.iter().any(|p| graph.is_ancestor(head_id, p.id));\n    if !pinned { /* pin before travelling */ }\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = travel(dest) {\n    if e.to_string().contains(\"must be pinned\") {\n        pin_head()?;\n        travel(dest)?;\n    } else { return Err(e); }\n}","preventionTips":["Pin HEAD whenever working detached","Attach to a branch before sideways/backward travel","Travel only to descendants while detached"],"tags":["cli","time-travel","detached-head","pin"],"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-16T04:17:20.429Z"}