# Line Endings: CRLF vs LF Use LF everywhere. Modern Windows editors (VS Code, Notepad, JetBrains) handle LF fine, and CRLF breaks shell scripts, Dockerfiles, and Makefiles (`bad interpreter: /bin/sh^M`). The only files that genuinely need CRLF are Windows batch files (`*.bat`, `*.cmd`). ## `.gitattributes` config Put this at your repo root. It normalizes everything to LF and only opts in CRLF where needed: ```gitattributes * text=auto eol=lf *.sh text eol=lf Makefile text eol=lf Dockerfile text eol=lf *.yml text eol=lf *.yaml text eol=lf *.bat text eol=crlf *.cmd text eol=crlf ``` This is better than `core.autocrlf` because `.gitattributes` lives in the repo — everyone gets the same behavior without remembering to configure their local Git. ([gitattributes docs](https://git-scm.com/docs/gitattributes), [GitHub guide](https://docs.github.com/articles/dealing-with-line-endings)) ## Windows/WSL users If you use Docker or WSL on Windows, also set: ```bash git config --global core.autocrlf false git config --global core.eol lf ``` This tells Git to trust `.gitattributes` and keep LF in the working tree too, avoiding `^M` surprises in containers. ## Pre-commit hook The [pre-commit](https://pre-commit.com/) framework includes [`mixed-line-ending`](https://github.com/pre-commit/pre-commit-hooks) in its official hooks repo: ```yaml - repo: https://github.com/pre-commit/pre-commit-hooks hooks: - id: mixed-line-ending args: ['--fix=lf'] ``` `--fix=lf` auto-converts to LF. Use `--fix=no` to just fail on mixed endings without modifying files. For [[Pre-commit#Frameworks|Lefthook]], use a shell one-liner: ```yaml check-crlf: glob: "*.{sh,yml,yaml,md,Dockerfile,Makefile}" run: "grep -rIlP '\\r {staged_files} && exit 1 || exit 0" ```