{"record":{"id":"f801e57714b99a27","repo":"babalae/better-genshin-impact","slug":"head","errorCode":null,"errorMessage":"仓库HEAD未指向任何提交","messagePattern":"仓库HEAD未指向任何提交","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs","lineNumber":1366,"sourceCode":"    /// <summary>\n    /// 检查指定路径是否为 Git 仓库（非文件式仓库）\n    /// </summary>\n    /// <param name=\"repoPath\">仓库路径</param>\n    /// <returns>如果是 Git 仓库返回 true，否则返回 false</returns>\n    private bool IsGitRepository(string repoPath)\n    {\n        return Repository.IsValid(repoPath) && !Directory.Exists(Path.Combine(repoPath, \"repo\"));\n    }\n\n    /// <summary>\n    /// 获取仓库中 repo/ 子目录的树对象\n    /// </summary>\n    private Tree GetRepoSubdirectoryTree(Repository repo)\n    {\n        var commit = repo.Head?.Tip;\n        if (commit == null)\n        {\n            throw new Exception(\"仓库HEAD未指向任何提交\");\n        }\n\n        // 脚本内容都在 repo/ 子目录下\n        var repoEntry = commit.Tree[\"repo\"];\n        if (repoEntry == null || repoEntry.TargetType != TreeEntryTargetType.Tree)\n        {\n            throw new Exception(\"仓库结构错误：未找到 repo/ 子目录\");\n        }\n\n        return (Tree)repoEntry.Target;\n    }\n\n    /// <summary>\n    /// 从中央仓库读取文件内容\n    /// </summary>\n    /// <param name=\"relPath\">相对于仓库根目录的路径</param>\n    /// <returns>文件内容，如果文件不存在则返回null</returns>\n    public string? ReadFileFromCenterRepo(string relPath)","sourceCodeStart":1348,"sourceCodeEnd":1384,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs#L1348-L1384","documentation":"Thrown by GetRepoSubdirectoryTree when repo.Head?.Tip is null — the current branch (HEAD) resolves to no commit. For a freshly cloned/fetched repo this means HEAD is unborn (no commits on the current branch) or detached with no target. LibGit2Sharp's Head.Tip is null on empty repositories.","triggerScenarios":"Calling GetRepoSubdirectoryTree(repo) on a Repository whose Head points to an unborn branch (just initialized, no commits) or whose HEAD ref is detached and points at a missing object. This is a precondition check before accessing commit.Tree[\"repo\"].","commonSituations":"Repository was cloned empty (remote had no commits on the checked-out branch); a partial/failed clone left HEAD pointing nowhere; the .git/HEAD file is corrupt; HEAD points to a branch that was never created locally after a fetch failure.","solutions":["Before calling GetRepoSubdirectoryTree, validate repo.Head.IsTip and repo.Head.Tip != null, and if null, re-clone or report a data-integrity error rather than proceeding.","Verify the clone completed successfully (check CloneRepository return / exception) before any tree access.","If HEAD is unborn, attempt to checkout a known branch: Commands.Checkout(repo, repo.Branches[\"release\"]) before reading the tree.","Run `git -C <repoPath> status` to inspect HEAD state; delete the repo directory and re-clone if HEAD is irrecoverable."],"exampleFix":"// before\nvar commit = repo.Head?.Tip;\nif (commit == null) throw new Exception(\"仓库HEAD未指向任何提交\");\n\n// after (diagnostic + recovery)\nvar head = repo.Head;\nif (head == null || head.Tip == null)\n{\n    _logger.LogError(\"仓库HEAD无效: head={Head}, branches={Branches}\",\n        head?.FriendlyName ?? \"null\",\n        string.Join(\", \", repo.Branches.Select(b => b.FriendlyName)));\n    throw new InvalidOperationException(\n        $\"仓库HEAD未指向任何提交（HEAD={head?.FriendlyName ?? \"null\"}），请删除仓库目录后重新克隆\");\n}","handlingStrategy":"validation","validationCode":"// Precondition helper to reuse across all Head.Tip sites\nstatic Commit EnsureHeadTip(Repository repo)\n{\n    var tip = repo.Head?.Tip;\n    if (tip == null)\n        throw new InvalidOperationException(\n            $\"仓库HEAD无提交 (branches: {string.Join(\",\", repo.Branches.Select(b=>b.FriendlyName))})\");\n    return tip;\n}","typeGuard":null,"tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"HEAD\"))\n{\n    // The repo is unusable; delete and re-clone\n    DirectoryHelper.DeleteReadOnlyDirectory(repoPath);\n    CloneRepository(repoUrl, repoPath, \"release\", null);\n}","preventionTips":["Always check repo.Head.Tip != null before tree access.","After CloneRepository, assert HEAD resolved before further operations.","Centralize the HEAD-validity check in one helper."],"tags":["git","libgit2sharp","head","empty-repo","precondition"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}