{"record":{"id":"7ebcd035513669ac","repo":"GitoxideLabs/gitoxide","slug":"the-conflict-checkout-did-not-leave-head-at-commi","errorCode":null,"errorMessage":"the conflict checkout did not leave HEAD at {commit}","messagePattern":"the conflict checkout did not leave HEAD at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/lib.rs","lineNumber":4374,"sourceCode":"    repository_path: &Path,\n    bare: bool,\n    title: &str,\n    changes: &mut Vec<edit::undo::RefChange>,\n) -> Result<()> {\n    let result = record_undo(repository_path, bare, title, changes);\n    changes.clear();\n    result\n}\n\nfn conflict_head(repository_path: &Path, bare: bool, commit: gix::ObjectId) -> Result<ConflictHead> {\n    let repository = open_repository(repository_path, bare, false)\n        .context(\"could not reopen the repository after checking out a conflict\")?;\n    let head = repository.head().context(\"could not inspect the conflicted HEAD\")?;\n    let id = head\n        .id()\n        .map(gix::Id::detach)\n        .context(\"the conflicted HEAD is unborn\")?;\n    anyhow::ensure!(id == commit, \"the conflict checkout did not leave HEAD at {commit}\");\n    let reference = head.referent_name().map(ToOwned::to_owned);\n    drop(head);\n    let name = reference\n        .clone()\n        .unwrap_or_else(|| \"HEAD\".try_into().expect(\"valid reference name\"));\n    anyhow::ensure!(\n        edit::undo::state(&repository, name.as_ref())? == edit::undo::State::Object(commit),\n        \"the conflicted HEAD attachment does not directly reference {commit}\"\n    );\n    let parents = repository\n        .find_commit(commit)\n        .context(\"could not find the checked-out conflict commit\")?\n        .parent_ids()\n        .map(gix::Id::detach)\n        .collect();\n    Ok(ConflictHead { reference, parents })\n}\n","sourceCodeStart":4356,"sourceCodeEnd":4392,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/lib.rs#L4356-L4392","documentation":"After performing a conflict checkout, the code re-opens the repository and verifies HEAD points exactly at the expected conflict commit. `anyhow::ensure!(id == commit, ...)` fires when HEAD resolved to a different object id, meaning the checkout did not land where the operation expected.","triggerScenarios":"A conflict checkout whose `head()` resolves to an id other than the target `commit` — e.g. another process moved HEAD between checkout and verification, or the checkout silently kept an existing HEAD position.","commonSituations":"Concurrent git operations (another terminal, IDE git integration) running while the tool checks out a conflict; a `git checkout` that failed partially; scripted automation touching HEAD mid-operation.","solutions":["Re-run the conflict checkout ensuring no other git process runs concurrently.","Verify HEAD manually (`git rev-parse HEAD`) and reset it to the expected commit before resuming.","Check for IDE/CI git integrations that may move HEAD during the operation."],"exampleFix":"// before\nanyhow::ensure!(id == commit, \"the conflict checkout did not leave HEAD at {commit}\");\n// after\nif id != commit {\n    repository.set_head_commit_to(commit)?;\n}\nanyhow::ensure!(id == commit, \"the conflict checkout did not leave HEAD at {commit}\");","handlingStrategy":"validation","validationCode":"let head_id = repo.head()?.id().map(|i| i.detach());\nif head_id != Some(commit) {\n    eprintln!(\"HEAD is not at the expected conflict commit; re-run the checkout\");\n    return;\n}","typeGuard":"fn head_is_at(repo: &gix::Repository, commit: gix::ObjectId) -> bool {\n    repo.head().ok().and_then(|h| h.id()).map(|i| i.detach()) == Some(commit)\n}","tryCatchPattern":"let result = conflict_checkout(commit);\nmatch result {\n    Err(e) if e.to_string().contains(\"did not leave HEAD at\") => retry_checkout(),\n    other => other,\n}","preventionTips":["Ensure no other git processes (IDE, hooks, scripts) run during conflict checkout.","Verify HEAD immediately after checkout and before further mutation.","Make checkout operations set HEAD atomically within one transaction."],"tags":["git","head","conflict","state-mismatch"],"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"}