{"record":{"id":"9172335a794682f2","repo":"gastownhall/beads","slug":"s-is-tracked-by-git-and-not-a-bd-managed-hook-bd","errorCode":null,"errorMessage":"%s is tracked by git and not a bd-managed hook; bd will not modify committed files it does not own\nUntrack it (git rm --cached) or move hooks to an untracked directory and re-run","messagePattern":"(.+?) is tracked by git and not a bd-managed hook; bd will not modify committed files it does not own\nUntrack it \\(git rm --cached\\) or move hooks to an untracked directory and re-run","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/hooks.go","lineNumber":837,"sourceCode":"\t}\n\tif fi.Mode()&os.ModeSymlink != 0 {\n\t\ttarget := \"unresolvable target\"\n\t\tif resolved, rerr := filepath.EvalSymlinks(hookPath); rerr == nil {\n\t\t\ttarget = resolved\n\t\t} else if link, lerr := os.Readlink(hookPath); lerr == nil {\n\t\t\ttarget = link\n\t\t}\n\t\treturn fmt.Errorf(\"%s is a symlink to %s; writing would rewrite the link target, not the hook\\nRemove the symlink (or leave that hook to its owner) and re-run\", hookPath, target)\n\t}\n\tif allowTracked {\n\t\treturn nil\n\t}\n\t// A tracked file is refused only when bd does NOT own it: writing into a\n\t// foreign tracked file dirties every clone that shares it (the wy-81fnur\n\t// incident). A bd-owned hook the user chose to commit (e.g. a team-shared\n\t// .beads/hooks/) is bd's to maintain — same policy as shared installs.\n\tif isGitTrackedFile(hookPath) && !isBdOwnedHookFile(hookPath) {\n\t\treturn fmt.Errorf(\"%s is tracked by git and not a bd-managed hook; bd will not modify committed files it does not own\\nUntrack it (git rm --cached) or move hooks to an untracked directory and re-run\", hookPath)\n\t}\n\treturn nil\n}\n\n// isBdOwnedHookFile reports whether the hook file at path is bd-managed:\n// either section-marker format or a legacy bd hook (shim or inline).\nfunc isBdOwnedHookFile(path string) bool {\n\tcontent, err := os.ReadFile(path) // #nosec G304 -- path is a hook location bd resolved\n\tif err != nil {\n\t\treturn false\n\t}\n\tif strings.Contains(string(content), hookSectionBeginPrefix) {\n\t\treturn true\n\t}\n\tversionInfo, err := getHookVersion(path)\n\treturn err == nil && versionInfo.IsBdHook\n}\n","sourceCodeStart":819,"sourceCodeEnd":855,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/hooks.go#L819-L855","documentation":"bd refuses to modify a git-tracked hook file that it does not own. Writing into a foreign committed file would dirty every clone sharing the repo (the wy-81fnur incident), so guardHookWritePath blocks the write when `git ls-files` shows the hook is tracked and the file lacks bd's section markers or legacy bd hook signature. This is a deliberate safety policy, not a transient failure.","triggerScenarios":"Running `bd hooks install` (via installHooksWithOptions -> guardHookWritePath) or applyHookMigrationExecution when the target hook path (e.g. .git/hooks/pre-commit or .beads/hooks/pre-commit) is committed to git and its content is not bd-generated.","commonSituations":"Teams commit custom pre-commit/pre-push hooks and later run bd hooks install into the same directory; a hook copied from another tool was added with `git add`; switching hooks directories while the old committed hooks still exist.","solutions":["Run `git rm --cached <hookPath>` to untrack the hook while keeping it on disk, then re-run the bd command","Move your custom hooks to an untracked directory (e.g. .beads/hooks/ or .githooks/) and re-run bd hooks install","If the hook is actually bd-generated (has bd section markers), no action needed — bd allows tracked bd-owned hooks; verify with a `git rm --cached` only if bd still refuses"],"exampleFix":"// before: hook tracked and foreign\n$ git add .git/hooks/pre-commit && bd hooks install\nerror: ... tracked by git and not a bd-managed hook\n// after\n$ git rm --cached .git/hooks/pre-commit\n$ bd hooks install\nHooks installed.","handlingStrategy":"validation","validationCode":"tracked=$(git -C \"$(dirname \"$hook\")\" ls-files --error-unmatch -- \"$(basename \"$hook\")\" 2>/dev/null && echo yes || echo no); [ \"$tracked\" = yes ] && git rm --cached \"$hook\" && echo untracked","typeGuard":"func isHookSafeToWrite(hookPath string) bool { return !isGitTrackedFile(hookPath) || isBdOwnedHookFile(hookPath) }","tryCatchPattern":null,"preventionTips":["Never `git add` files under .git/hooks/ or foreign hook scripts bd may manage","Keep team hooks in an untracked or bd-owned directory like .beads/hooks/","Check `git ls-files -- <hookPath>` before running bd hooks install in a repo with custom hooks"],"tags":["git","hooks","safety-guard"],"backgroundTag":"tracked-file-modify-refused","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}