{"record":{"id":"7b65fb6c10e2d0d6","repo":"nikivdev/code","slug":"refusing-to-commit-generated-files","errorCode":null,"errorMessage":"Refusing to commit generated files","messagePattern":"Refusing to commit generated files","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/commit.rs","lineNumber":6698,"sourceCode":"\n    for (path, _) in &staged {\n        let _ = git_run_in(repo_root, &[\"reset\", \"HEAD\", \"--\", path]);\n    }\n\n    if !ignore_entries.is_empty() {\n        println!(\"Added ignore rules for generated files and unstaged them.\");\n    } else {\n        println!(\"Unstaged generated files.\");\n    }\n    if saw_personal_tooling {\n        println!(\n            \"Personal tooling paths (.beads/) should be ignored globally, not in project .gitignore.\"\n        );\n        println!(\"Run `f gitignore policy-init` and `f gitignore fix` to clean existing repos.\");\n    }\n    println!(\"Re-run `f commit` after verifying the changes.\");\n    println!(\"Set FLOW_ALLOW_UNWANTED_COMMIT=1 to override.\");\n    bail!(\"Refusing to commit generated files\");\n}\nfn unwanted_staged_paths(repo_root: &Path) -> Vec<(String, String)> {\n    let output = Command::new(\"git\")\n        .args([\"diff\", \"--cached\", \"--name-status\", \"-z\"])\n        .current_dir(repo_root)\n        .output();\n\n    let Ok(output) = output else {\n        return Vec::new();\n    };\n    if !output.status.success() {\n        return Vec::new();\n    }\n\n    let mut out = Vec::new();\n    let raw = String::from_utf8_lossy(&output.stdout);\n    let parts: Vec<&str> = raw.split('\\0').collect();\n    let mut i = 0;","sourceCodeStart":6680,"sourceCodeEnd":6716,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/commit.rs#L6680-L6716","documentation":"The tool scans staged files (git diff --cached --name-status) against a policy of unwanted/generated paths (e.g. .beads/, lockfiles, build artifacts) and aborts the commit if any match. It prints remediation guidance (f gitignore policy-init / fix) and allows override with FLOW_ALLOW_UNWANTED_COMMIT=1.","triggerScenarios":"Running `f commit` with generated artifacts or personal-tooling paths staged, detected by unwanted_staged_paths() — e.g. a .beads/ directory staged, or unwanted paths listed in project .gitignore instead of global gitignore.","commonSituations":"`git add .` picking up build output or generated files, .beads/ accidentally tracked because it was committed before being ignored, gitignore policy not initialized in a new repo, or generated files newly appearing after a build.","solutions":["Unstage the listed paths: `git restore --staged <path>`","Run `f gitignore policy-init` and `f gitignore fix` to set up correct ignore rules","Regenerate ignored artifacts locally instead of committing them","Set FLOW_ALLOW_UNWANTED_COMMIT=1 only if committing the generated files is intentional"],"exampleFix":"// before (shell)\ngit add . && f commit   # build/dist artifacts staged\n// after (shell)\nprintf 'dist/\\n.beads/\\n' >> .gitignore && git rm -r --cached dist .beads && f commit","handlingStrategy":"validation","validationCode":"let out = Command::new(\"git\")\n    .args([\"diff\", \"--cached\", \"--name-only\"])\n    .output()?;\nlet unwanted = [\".beads/\", \"dist/\", \"build/\"];\nlet staged = String::from_utf8_lossy(&out.stdout);\nlet bad: Vec<&str> = staged.lines()\n    .filter(|p| unwanted.iter().any(|u| p.starts_with(u)))\n    .collect();\nif !bad.is_empty() { eprintln!(\"unstage generated files: {:?}\", bad); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = tool.commit(msg) {\n    if e.to_string().contains(\"generated files\") {\n        eprintln!(\"run `f gitignore policy-init` and `f gitignore fix`, then re-stage\");\n    } else { return Err(e.into()); }\n}","preventionTips":["Initialize gitignore policy in every repo (`f gitignore policy-init`)","Put personal tooling paths in global gitignore, not project .gitignore","Check `git diff --cached --name-status` before committing","Never set FLOW_ALLOW_UNWANTED_COMMIT=1 in CI defaults"],"tags":["git","guardrail","generated-files","gitignore"],"backgroundTag":"generated-files-committed","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}