Git autocrlf 拉取代码换行符 LF 与 CRLF 设置
默认设置为 lf
git config --global core.autocrlf input
上述设置 windows 默认值是 true
true:git在提交时自动替换行尾符crlf为lf,windows系统在签出代码时,再把lf转换为crlfinput:git在提交时自动替换行尾符crlf为lf,签出代码时,不转换false:git在提交时不转换,提交crlf行尾符到仓库,签出时,不转换
三个值该怎么选
记住一个前提就好判断:仓库里应该统一存 LF。这不是洁癖,是因为 Git 的 diff 是按行比对文本的,仓库里 LF 和 CRLF 混着存,会出现「明明没改内容,diff 却显示整个文件全变了」的情况。
按这个前提:
- Windows 开发者用
true:仓库存 LF,本地检出成 CRLF。适合还在用不认 LF 的老工具(早期的记事本、某些 Windows 专用编辑器)的情况。 - Windows 开发者也可以用
input:仓库存 LF,本地也是 LF。现在 VS Code、WebStorm、Windows Terminal、PowerShell 全都能正常处理 LF,所以我更推荐这个——本地和仓库一致,少一层转换就少一类问题。 - macOS / Linux 用
input:系统本来就是 LF,input只是多一层保险(万一从别处粘进来 CRLF 内容,提交时会被纠正)。 false基本别用:它等于完全不管,仓库里存什么全看每个人本地是什么,最终必然混乱。
更好的做法是 .gitattributes
core.autocrlf 是每个人本地的配置,团队里总有人没配或者配错。.gitattributes 提交进仓库,对所有人生效,优先级也高于 core.autocrlf,这才是可靠的方案:
# .gitattributes
# 让 git 自己判断哪些是文本文件,文本文件在仓库里一律存 LF
* text=auto eol=lf
# 显式指定某些类型(比 text=auto 的猜测更可靠)
*.js text eol=lf
*.ts text eol=lf
*.vue text eol=lf
*.json text eol=lf
*.md text eol=lf
*.css text eol=lf
# Windows 批处理和 PowerShell 脚本必须是 CRLF,否则可能执行异常
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
# 二进制文件明确标出来,禁止任何转换
*.png binary
*.jpg binary
*.woff2 binary
*.pdf binary
*.zip binary
几个属性的含义:
text:声明这是文本文件,参与换行符转换。text=auto:让 git 检测文件内容(含 NUL 字节就当二进制),检测为文本的才转换。eol=lf/eol=crlf:检出到工作区时用哪种换行符。仓库里始终是 LF。binary:等于-text -diff,完全不转换、也不做文本 diff。
* text=auto eol=lf 这一行是现在最常见的配置,效果是「不管谁在什么系统上,工作区和仓库都是 LF」。*.bat 那几行是必要的例外——CMD 解析 .bat 时对 LF 的兼容性不好,可能出现莫名的执行错误。
配置了 .gitattributes 之后要归一化一次
这是最容易漏的一步。新加的规则只对之后的提交生效,仓库里已经存成 CRLF 的文件不会自动变。要一次性纠正:
# 1. 先确保工作区干净(有未提交改动的话先 stash 或 commit)
git status
# 2. 清空 index,让 git 忘记所有文件的缓存状态
git rm --cached -r .
# 3. 按新规则重新添加,这一步会做换行符转换
git reset --hard
git add .
# 4. 提交这次归一化
git commit -m "chore: normalize line endings"
Git 2.16+ 有个更简洁的命令做同样的事:
git add --renormalize .
git commit -m "chore: normalize line endings"
这个提交的 diff 会非常大(所有原本是 CRLF 的文件全部显示改动),所以应该单独提交、不夹带任何功能改动,并且提前跟团队说好,避免别人 rebase 时撞上巨型冲突。
常见症状对照
warning: LF will be replaced by CRLF in xxx:这不是错误,只是告诉你 core.autocrlf=true 正在做转换。嫌烦可以关掉提示:
git config --global core.safecrlf false
但更好的处理是理解它在说什么,然后决定 autocrlf 该配什么值。
整个文件显示全部改动,但内容看着一样:典型的换行符问题。验证:
# 忽略换行符差异看 diff,如果输出为空就确认是换行符导致的
git diff --ignore-cr-at-eol
# 直接看文件的实际换行符($ 表示行尾)
cat -A src/a.ts | head -3
# ^M$ 结尾是 CRLF,只有 $ 是 LF
# 看 git 认为这个文件的属性是什么
git check-attr text eol -- src/a.ts
Shell 脚本报 bad interpreter: /bin/bash^M:.sh 文件被转成了 CRLF,#!/bin/bash 后面多了个 \r,系统把它当成解释器路径的一部分。在 .gitattributes 里加一行:
*.sh text eol=lf
ESLint / Prettier 报 Delete ␍:Prettier 的 endOfLine 默认是 lf,和本地的 CRLF 文件不符。两边对齐即可:
// .prettierrc
{ "endOfLine": "lf" }
配了 .gitattributes 的 eol=lf 之后这个报错自然就消失了,因为工作区里的文件本来就是 LF。反过来如果团队用 autocrlf=true(工作区是 CRLF),Prettier 就得配 "endOfLine": "crlf" 或 "auto"。
检查仓库里有没有混用
# 列出所有被 git 认为是文本、且仓库里存了 CRLF 的文件
git ls-files --eol | grep 'i/crlf'
git ls-files --eol 的输出里 i/ 是 index(仓库)中的换行符,w/ 是工作区的。理想状态是 i/lf,w/ 按你的 eol 设置。看到 i/crlf 或者 i/mixed 就说明该做一次归一化了。

还没有留言,来发表第一条吧~