fix(eol): make *.ps1 canonical LF + no BOM for shebang compat#347
Conversation
Removes the *.ps1 CRLF + UTF-8-BOM overrides from .gitattributes and
.editorconfig. Required for the '#!/usr/bin/env pwsh' shebang line at
the top of every script under scripts/ to work as an executable on
Linux/macOS:
- CRLF: kernel parses '#!/usr/bin/env pwsh\r' and looks for an
interpreter literally named 'pwsh\r' — exec fails.
- UTF-8 BOM: bytes EF BB BF appear before '#!', so the kernel
doesn't recognize the file as a shebang script at all.
The original 'PowerShell uses CRLF for Windows compatibility'
rationale predates PowerShell 7+ (cross-platform). Modern PS Core
handles LF on Windows transparently. The PowerShell team's own
canonical repos (PowerShell/PowerShell, PSScriptAnalyzer) all use
LF + no BOM.
What changes
- .gitattributes: '*.ps1 text eol=crlf' -> '*.ps1 text' (defaults to
eol=lf via the global '* text=auto eol=lf' rule)
- .editorconfig [*.ps1]: drop 'end_of_line = crlf' and
'charset = utf-8-bom'; default LF + utf-8 (no BOM) applies
What does NOT change
- Files in the index: already LF (have been since day one — the
CRLF rule was aspirational policy that never matched reality).
No file content rewrites in this PR.
- Windows users with core.autocrlf=true: still get CRLF in their
working tree on checkout; only the index/wire format is LF.
- Indent: still 4 spaces for *.ps1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Aligns PowerShell script encoding/line-ending policies with cross-platform shebang execution requirements by removing CRLF and UTF-8 BOM overrides for *.ps1, so #!/usr/bin/env pwsh scripts can be executed directly on Linux/macOS.
Changes:
- Updates
.gitattributesto stop forcing*.ps1toeol=crlf, relying on the repo’s LF normalization. - Updates
.editorconfigto removeend_of_line = crlfandcharset = utf-8-bomoverrides for*.ps1. - Rewrites comments in both files to document the shebang rationale and cross-platform behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
.gitattributes |
Removes the *.ps1 CRLF override and updates documentation around PowerShell script portability. |
.editorconfig |
Removes *.ps1 CRLF/BOM overrides so PS scripts follow the global LF + UTF-8 (no BOM) defaults. |
| # PowerShell scripts: LF line endings, no BOM. Required for the | ||
| # `#!/usr/bin/env pwsh` shebang to work on Linux/macOS — the kernel | ||
| # parses CR as part of the interpreter name (looking for `pwsh\r`), | ||
| # and a UTF-8 BOM before `#!` prevents shebang recognition entirely. | ||
| # Modern PowerShell 7+ handles LF on Windows transparently; Git's | ||
| # autocrlf still gives Windows users CRLF in their working tree if | ||
| # desired without forcing CRLF into the index. | ||
| *.ps1 text |
There was a problem hiding this comment.
Fixed in 55fb82a — changed *.ps1 text to *.ps1 text eol=lf to match the explicit-eol convention every other entry in this file uses. Both files are now self-consistent with their own surrounding conventions.
| # (CR breaks kernel exec lookup; BOM before `#!` prevents shebang recognition.) | ||
| # Modern PowerShell 7+ handles LF on Windows transparently; users with | ||
| # autocrlf=true still get CRLF in their working tree on checkout. | ||
| [*.ps1] |
There was a problem hiding this comment.
Addressed in 55fb82a — went with the "fix the comment" path rather than adding explicit end_of_line / charset, because every other [*.xxx] section in this file only overrides what differs from the [*] defaults. Adding explicit settings here would be inconsistent with the rest of the file's pattern. Updated the comment to accurately describe that LF + no-BOM come from the global section above (and why it matters — the shebang).
…comment fix: address Copilot review on #347 (explicit eol=lf + comment honesty)
Summary
Drop the
*.ps1CRLF + UTF-8-BOM overrides in.gitattributesand.editorconfig. Required for the#!/usr/bin/env pwshshebang at the top of every script inscripts/to actually work as an executable on Linux/macOS.The shebang problem
Two ways the current overrides break shebang invocation:
#!/usr/bin/env pwsh\rand tries to find an interpreter literally namedpwsh\r— fails. (\ris part of the parsed interpreter path.)EF BB BFappear before#!, so the kernel doesn't recognize the file as a shebang script at all.Either alone breaks
./script.ps1. Together, they make it doubly broken on non-Windows.Why "PowerShell uses CRLF" was outdated rationale
That convention came from the Windows-PowerShell-5.1-and-earlier era when PS only ran on Windows. The current canonical sources have all standardized on LF:
PowerShell/PowerShellrepo: LF, no BOMPSScriptAnalyzer: LF, no BOMModern PowerShell 7+ (PS Core) is cross-platform and handles LF on Windows transparently.
What changes
.gitattributes*.ps1 text eol=crlf*.ps1 text(defaults toeol=lfvia the global rule).editorconfig [*.ps1]end_of_line = crlf,charset = utf-8-bomComments rewritten to explain the shebang rationale.
What does NOT change
core.autocrlf=true(Git for Windows default) still gives CRLF in working tree on checkout. Only the index/wire format is LF — which is what it's always been.*.ps1.Why this PR is so small
Today's state: index is
i/lf, attr sayseol=crlf, working tree on Windows isw/crlf(autocrlf). After this PR: indexi/lf, attr sayseol=lf, working treew/crlfon Windows /w/lfon Linux/macOS. The only difference is the attr declaration aligning with what's already in the index.Note about the protected-files guard
This PR touches
.editorconfig(protected) — theDetect .NET Projectsguard will fail it. Maintainer override required.Follow-up
After merge, sync to the 24 affected active repos (each has the same
[*.ps1]overrides). Per-repo PRs, each ~12 lines. Each will need maintainer override too — same pattern as previous fleet-wide config-touching syncs.Test plan
git ls-files --eol scripts/*.ps1showsi/lf w/* attr/text eol=lfeverywherechmod +x scripts/setup.ps1 && ./scripts/setup.ps1 --helpworks on Linux/macOS via shebang