Windows 上纯 Agent Vibe Coding:先把 Git 的 autocrlf 设为 input
以 Agent 为主的 Windows 开发环境里,行尾差异是最容易被忽略的干扰源。这份检查清单从 core.autocrlf 讲到 .gitattributes 与写入约定,明确 input 能做什么、不能做什么。
在 Windows 上把写代码、改文件、执行命令的大部分工作交给 AI Agent 时,环境准备阶段就值得检查一个容易被忽略的设置:core.autocrlf。
对于以现代跨平台工具链为主、希望工作区尽量使用 LF 的项目,我的建议是优先使用 core.autocrlf=input,不要无意识地沿用 true。
它的价值不是提高代码质量,也不是让 Agent 突然变聪明,而是减少一类很烦人的干扰:仓库里的 LF 文本被检出成 CRLF,随后脚本、格式检查或文本补丁又因为这层差异出问题。
不过先把边界说清楚:input 不是"全项目一键变成 LF",更不是修复所有 bug 的万能开关。它控制的是 Git 的自动行尾转换;项目属性、编辑器、Agent 的写文件方式和已有文件内容,都需要分别检查。
为什么纯 Agent 开发更值得注意
Vibe Coding 是用自然语言向 AI 表达需求,由 AI 编写代码,再根据运行结果持续迭代的开发方式。这里说的"纯 Agent",是指文件编辑、补丁应用和命令执行主要由 Agent 完成,而不是人始终打开编辑器逐行检查。
这不意味着行尾问题只会发生在 AI 开发中。区别在于:人手动编辑时可能会看到编辑器右下角的 LF 或 CRLF;Agent 连续调用文件工具和终端时,这些看不见的字节更容易被忽略。
换行符主要有两种:
- LF:
\n,常见于 Linux、macOS 和跨平台源码。 - CRLF:
\r\n,常见于 Windows 文本环境。
屏幕上都是换一行,文件中的字节却不同。如果 Git、Agent 的写文件工具、格式化器和运行环境对它们的处理不一致,就可能出现:
- Shell 脚本在 WSL、Linux 容器或 CI 中出现
^M、$'\r'或解释器路径相关错误。 - Agent 使用逐字匹配的文本替换或某些补丁工具时,找不到它预期的 LF 片段。
- 格式化或 lint 检查要求 LF,而本地文件被保存成 CRLF,导致检查失败。
- 工具把行尾差异展示成大面积变更,让真正的逻辑修改难以审查。
所以更准确的说法不是"Windows 把代码弄坏了",而是:同一份文本经过多个工具时,行尾约定不一致。
input、true、false 到底差在哪
Git 官方的 core.autocrlf 文档说明,true 相当于启用自动文本识别并将输出行尾设为 CRLF;input 则不进行输出转换。
| 配置 | 检出到工作区时 | 添加到暂存区时 |
|---|---|---|
| true | 对适用的文本文件,将 LF 转成 CRLF | 将 CRLF 规范为 LF |
| input | 不做自动输出行尾转换 | 将识别的 CRLF 规范为 LF |
| false | 不启用自动行尾转换 | 不启用自动行尾转换 |
这里的"适用"很重要:不是所有文件、所有历史状态都会被无条件转换。二进制检测、路径属性,以及已经以 CRLF 存入索引的文件,都可能影响结果。
真正的转换通常发生在 git add
理解 Git 时最好区分三个位置:
工作区:Agent 实际编辑、程序实际运行的文件
↓ git add,可能执行输入规范化
暂存区 / 索引:准备写入下次提交的内容
↓ git commit
提交:记录暂存区中的快照大家常说"提交时转成 LF",但日常流程中转换通常在 git add 把文件放进索引时就发生了。
这也解释了一个关键现象:工作区的文件仍是 CRLF,但暂存区中的版本已经是 LF。这不是失败,正是 input 可能产生的正常结果。
设置 input 之后:
- 已经存在于工作区的 CRLF 文件不会立刻改变;
- 编辑器或 Agent 下次保存文件时,不会因此自动使用 LF;
- 仓库里原本存着的 CRLF,不会因为修改配置就全部变成 LF;
- 显式路径属性和其他内容过滤器,仍可能影响检出或暂存结果。
为什么不直接推荐 false
false 可以关闭 core.autocrlf 自身的自动转换。但在没有项目规则兜底时,如果某个 Agent 工具写入了 CRLF,它也不会通过这项配置在暂存时被规范成 LF。
input 的折中更适合本文的目标:不主动把仓库中的 LF 扩展为工作区 CRLF,同时为适用文本保留输入规范化。
不过 false 不等于错误。一个项目如果已经用完整的 .gitattributes 精确管理行尾,false 配合项目规则也可以是合理方案。
第一步:只读检查,不急着改
先在项目根目录打开 PowerShell 或 Git Bash:
git status --short
git config --show-origin --show-scope --get-all core.autocrlf
git config --show-origin --show-scope --get-all core.eol
git config --show-origin --show-scope --get-all core.safecrlf
git ls-files --eol重点检查四件事:
- 有没有尚未处理的改动。 先分清已有业务修改和行尾问题,不要混在一起修。
- 配置从哪里来。 system、global、local 等作用域可能有不同值。
- 项目有没有属性规则。 查看
.gitattributes、.editorconfig,必要时也检查.git/info/attributes。 - 索引和工作区分别是什么行尾。 不要只看编辑器状态栏。
确认某个实际路径的最终属性:
git check-attr text eol filter working-tree-encoding -- scripts/build.shunspecified 只表示该属性没有显式指定,不表示最终一定不转换。
尤其要记住:Windows 原生 Git、WSL 里的 Git,以及 Agent 使用的另一套 Git,可能读取不同配置。 检查与设置都应该在 Agent 实际执行任务的环境里完成。
第二步:选择设置范围
先只影响当前仓库:
git config --local core.autocrlf input这会修改当前仓库的本地配置,不会自动分享给协作者,也不会替你改写源码。
确认适用后,作为个人默认值:
git config --global core.autocrlf input不必把两条命令机械地都执行一遍:先决定你要改当前仓库,还是个人默认值。
第三步:看文件,而不只看配置值
git ls-files --eol -- scripts/build.sh你可能看到:
i/lf w/crlf attr/ scripts/build.sh含义是:索引中是 LF、工作区是 CRLF、没有显式的文本或行尾属性。
若看到 i/lf w/crlf,不要立刻断言 input 没生效。 它可能只是没有改写已有工作区文件,而这正是预期行为。
想亲眼验证?用独立实验目录
以下实验会创建一个新目录和临时测试仓库,请在项目之外运行:
New-Item -ItemType Directory -Path git-eol-input-demo -ErrorAction Stop
Set-Location git-eol-input-demo
git init
git config --local core.autocrlf input
[System.IO.File]::WriteAllBytes(
(Join-Path (Get-Location).Path 'sample.txt'),
[byte[]](111, 110, 101, 13, 10, 116, 119, 111, 13, 10)
)
git add -- sample.txt
git ls-files --eol -- sample.txtGit Bash 版本:
mkdir git-eol-input-demo && cd git-eol-input-demo
git init
git config --local core.autocrlf input
printf 'one\r\ntwo\r\n' > sample.txt
git add -- sample.txt
git ls-files --eol -- sample.txt在没有额外属性和安全配置干预时,两版都应显示类似 i/lf w/crlf。实验不需要提交。
项目已有 .gitattributes 时,先服从项目约定
全局配置是个人默认值,.gitattributes 则是对路径的规则声明。显式的 text、eol 等属性可以决定相应路径的行为:
*.sh text eol=lf
*.bat text eol=crlf
*.png -text这三条分别表达:Shell 脚本使用 LF 工作区行尾;批处理文件使用 CRLF;PNG 不做文本行尾转换。
即使 core.autocrlf=input,适用的 eol=crlf 路径规则仍然可以在检出时输出 CRLF。
新项目可以考虑怎样写
如果已经确认默认 LF 适合它:
# 默认识别文本;适用文本检出时使用 LF
* text=auto eol=lf
# 项目确实需要 CRLF 的文件,放在默认规则之后
*.bat text eol=crlf
*.cmd text eol=crlf
# 已知二进制文件,明确排除行尾转换
*.png -text
*.jpg -text
*.pdf -text
*.zip -text不要把首行轻率地改成 * text eol=lf:它会把所有匹配文件强制按文本处理,可能损坏二进制内容。
已有项目不要直接覆盖 .gitattributes。里面可能还管理 Git LFS、过滤器、编码或合并行为。
工作区也要 LF?还得约束写文件的工具
程序运行的是工作区文件,而不是暂存区快照。如果 Shell 脚本仍是 CRLF,单靠 input 并不能保证本地执行恢复正常。
因此还需要另一层约定:让编辑器和 Agent 在写入适用文本文件时直接使用 LF。
root = true
[*]
end_of_line = lf
[*.bat]
end_of_line = crlf对 Agent 可以直接补充一条项目要求:
修改前先读取现有
.gitattributes和.editorconfig。无明确例外的源码与脚本使用 LF;保留项目指定的 CRLF、编码、二进制和测试夹具规则。不要为了统一行尾触发全仓格式化。
Git 管暂存和检出边界,编辑器与 Agent 管文件如何写入。这两层职责不能互相替代。
已有 CRLF,怎样稳妥处理
先区分问题的位置:
i/lf w/crlf:仓库记录的内容已经符合预期,问题只在本地运行文件上。针对真正需要 LF 的文件做转换即可。i/crlf w/crlf:不能承诺"改成input后随便 add 一次就会全修好"。
若确需重新规范化:
git status --short
git check-attr text eol filter working-tree-encoding -- scripts/build.sh
git add --renormalize -- scripts/build.sh
git diff --cached -- scripts/build.sh
git diff --cached --check
git ls-files --eol -- scripts/build.sh--renormalize 会为指定范围的已跟踪文件重新执行输入清理流程,把结果放进索引;它不会替你改工作区文件。
也不要让 Agent 用"删除工作区再检出"或 git reset --hard 碰运气:这既可能丢失修改,也未必针对真正的问题。
哪些情况不要直接照抄
- 项目明确要求某些工作区文件使用 CRLF。 保留路径级例外。
- 文件必须逐字节保真。 二进制、签名数据、补丁样本、测试夹具。
- 项目使用特殊编码、Git LFS 或其他内容过滤器。 UTF-16 不能按普通 UTF-8 机械处理。
- 团队已经有成熟行尾规范。 不要让个人默认值替代团队决策。
- 仓库已有混合行尾、大量未提交修改或正在合并冲突。
- 报错根本不是行尾引起的。 依赖版本、路径大小写、权限、编码和业务逻辑问题,不会因为
input而消失。
我的最终建议
在 Windows 上主要依靠 Agent 开发跨平台项目时,我会把下面这条命令列入环境准备清单:
git config --global core.autocrlf input它提供了一个实用的默认方向:不额外把 LF 检出成 CRLF,同时让适用文本在进入索引时规范为 LF。
真正稳定的做法是三层规则配合:个人 Git 配置减少意外转换、项目 .gitattributes 明确路径约定、编辑器与 Agent 按约定写文件。最后用 git config --show-origin、git check-attr 和 git ls-files --eol 验证事实,而不是只凭一个设置值判断成功。
input 不能包治百病,但它能让这类 Windows Agent 工作流少一个容易被忽略的变量。