Skip to content

Pre-push hook fails on Windows due to missing repo-wide line-ending policy #1254

@sanil-23

Description

@sanil-23

Summary

.husky/pre-push reliably fails on Windows worktrees because core.autocrlf=true (the Git-for-Windows default) plus a missing repo-wide .gitattributes cause pnpm format:check to mark ~600 unrelated files dirty on every pre-push. The hook auto-fixes them with pnpm format but still exits 1 because FORMAT_EXIT was captured before the fix.

Problem

On Windows with default Git config, files arrive on disk with CRLF line endings (autocrlf converts LF → CRLF on checkout). Prettier's project config enforces LF, so pnpm format:check flags the entire tree as needing format. The hook script's design bug is that it captures FORMAT_EXIT before the auto-fix runs, so even after the fix succeeds the hook still reports failure.

Impact

Steps to reproduce (Windows + Git Bash + Git for Windows default config)

  1. git clone https://github.com/tinyhumansai/openhuman.git.
  2. Make a one-line change to any TS or Rust file.
  3. git commit -m "test" && git push -u origin <branch>.
  4. Pre-push hook fails: pnpm format rewrites ~600 unrelated files; FORMAT_EXIT=1 short-circuits the hook even after auto-fix.

Environment: Windows 11, Git for Windows 2.x, core.autocrlf=true (default), no repo-wide .gitattributes.

Solution

Two changes, both small:

  1. Add a repo-root .gitattributes enforcing * text=auto eol=lf plus explicit binary excludes for the file types in the tree (.png, .ico, .icns, .lottie, etc.). Git stores and checks out everything with LF regardless of core.autocrlf.
  2. Document git config --local core.autocrlf false in CONTRIBUTING.md (or wherever onboarding lives) for Windows contributors, so the working-tree state matches the committed state from the start.

Separate but related: fix .husky/pre-push to capture FORMAT_EXIT after the auto-fix succeeds, so the hook actually self-heals instead of always exiting 1 when format check trips. Same for LINT_EXIT.

Acceptance criteria

  • Repro gone — Cloning and editing a file on Windows no longer makes git status show hundreds of unrelated files modified after pnpm format.
  • Pre-push hook self-heals — When format:check fails, pnpm format auto-fixes, and the hook exits 0 with the auto-fix staged (or surfaces a clear "stage and re-push" instruction).
  • Regression safety.gitattributes covers the file extensions actually used in the tree (binary/text classification), and a comment documents the policy.
  • Diff coverage ≥ 80% — the fix PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/coverage.yml).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions