网易首页 > 网易号 > 正文 申请入驻

聊聊关于AI写代码的编码格式和行尾问题

0
分享至

问题背景

2026年起,AI越来越厉害,以前都是手写代码,后来有网页版早期的ChatGPT和Deepseek,开始资讯AI辅助写代码,最多就是复制AI给出的片段,贴到本地再适应本地项目。

而2026年后,完全可以让AI直接写Unity的或者其他引擎的代码了,甚至MCP可以直接帮你在Unity里编译好,完整debug后再交付给你,非常爽。

但是,我们团队开发一段时间后,发现了一个以前手写代码不会有的问题,那就是出现各种编码和行尾不一致的问题,一旦提交git或者svn,就会发现无缘故多了很多明明没改但提示变了的文件。这些误报会消耗很多时间精力去筛查,非常不值得。

调查情况

先看Unity这边,由于一般是用的VS来写的代码,的行尾和编码由编辑器决定的,默认行尾是CRLF,编码格式是UTF-8带BOM。但是AI编写的代码, 就由AI模型的习惯决定了,根据训练资料有关,大多LF和UTF8无BOM。





最大坑点是,有可能AI写好的代码,你用Visual Studio打开,不小心就会自动按照VS的默认设置改掉了编码和行尾,相反AI写的也可能会改掉原有文件的编码和行尾,来回变化,导致查看差异时很多误报。

到底有无BOM两者有什么区别



虽然都是UTF8,但是缺又不完全一样,到底什么区别,因此我也资讯了下AI答案:

BOM 是文件开头的三个字节,EF BB BF。它原本是给「不知道这是 UTF-8」的老工具打的一个标记。

C# 在 Windows 上的默认行为,是存成 UTF-8 带 BOM,有些配置下干脆是系统本地编码,中文 Windows 就是 GBK。

带 BOM 编译没问题,.NET 编译器认识它。麻烦出在别处。多出的三个字节会让某些 diff 工具把第一行算成改过。Linux 上的一些脚本、模板引擎、拼接工具会把 BOM 当成内容,输出里冒出一个看不见的字符。某些 JSON 解析器和字符串比较对 BOM 敏感。最烦的是抖动,同一个文件在「带 BOM」和「不带 BOM」的两台机器之间来回转,diff 会一直抖。

那到底统一成什么比较好呢?

Unity 的文档里提到,含非 ASCII 字符的脚本建议用带 BOM 的 UTF-8,保证各种环境都能正确识别编码。而 AI 生成的代码天然不带 BOM。一个主要靠 AI 写代码的项目,两边的默认值正好相反。



我其实一开始挺犹豫,让AI扫了我当前的项目编码情况,带和不带各站一半就很尴尬,特别是含中文注释的UTF8无BOM不知道有没有风险。



不过根据AI提供的资讯,带BOM主要用于老工具的识别,目前可能也用不到,无论带和不带,现在单独打开编辑器看中文注释都是没问题的。

项目往后主要靠AI写代码的话,还是应该顺着AI的默认值走,少一层来回转换的必要。所以我选择了B方案。

再看行尾的问题

AI 天然就是 LF,而Windows手写的默认是CRLF。不过我让AI实际扫描我当前项目,LF已成事实主流了。



因为同样的理由,未来会选择用AI写代码为主,所以顺应AI主流直接用LF作为规范统一是最合适的选择了。



约定成写入规范

一次性的整改只是临时的,要长期规范要真正写入成一个规范文件根治才行,AI检查后说我治理机制全缺,让我写这3个规范文件:

.editorconfig /.gitattributes /svn:eol-style



说实话以前手写代码的时候,我根本没见过这几个东西,从来没用过也能跑。但根据AI给出的资讯,其实他们在AI时代很重要,以下是AI给出的介绍:

.editorconfig卡在编辑器这一端。你新建或保存一个文件时,编辑器会先读它,按里面的规定决定用什么缩进、什么字符集、什么行尾。它是一份写给编辑器看的约定。

.gitattributes和svn:eol-style卡在版本控制这一端。文件入库的那一刻,它们负责把行尾和文本类型归一化。它们不关心你用什么工具写,只认提交这个动作。

最后一道是提交前检查,pre-commit 或者 CI。前两道都设好了,还是可能有人或者某个工具绕过去,那就靠它把漏网的文件拦下来。

最简单的文件.editorconfig

在项目根目录放一个.editorconfig,写这么几行就够了。

root = true

charset = utf-8

end_of_line = lf

insert_final_newline = true

trim_trailing_whitespace = true

indent_style = space

indent_size = 4

[*.{json,yml,yaml}]

indent_size = 2

[*.md] trim_trailing_whitespace = false

root = true表示这是最顶层,编辑器往上找到这里就停,不再往父目录找。

charset写utf-8,注意不是utf-8-bom。这一条就是「编码用 UTF-8、不带 BOM」的写法。

end_of_line写lf,对应「行尾用 LF」。

几种主流编辑器都原生读它,VS Code、Rider、Visual Studio 2022 都不用装插件。写一次,全项目生效,没有运行时成本。

放哪儿也简单。项目根目录最省事。如果只想管住 Unity 工程,放在Assets/下面也完全安全,Unity 会忽略点开头的文件,不会给它生成.meta,也不会当资源导入。

还有个容易忽略的点。VS 和 Rider 都是启动时读它,改完记得重开一次编辑器,不重开不生效。

它的弱点也很明确。它不强制。只在编辑器愿意遵守的时候才生效。你用命令行工具直接写文件、用脚本批量生成文件,或者让某个工具直接落盘,它一律管不着。

Git版本控制的.gitattributes

如果你用 Git,在仓库根目录放一个.gitattributes。

* text=auto eol=lf

*.cs text eol=lf

*.sln text eol=crlf

*.bat text eol=crlf

*.cmd text eol=crlf

*.png binary

*.dll binary

* text=auto eol=lf这一行是现在的推荐起手式。git 提交时把文本文件的行尾统一成 LF 存进仓库,检出到工作区也按 eol 走。仓库里永远只有一种行尾,跨平台协作不会互相覆盖。

下面几行是明确点名。.cs走 LF,.sln和 Windows 批处理按各自的要求单独给 CRLF,图片和 dll 直接标成 binary,别让 git 去猜。

SVN属性的svn:eol-style

SVN 没有 .gitattributes 那种放在仓库里、人人可见的声明文件。它的做法是给文件挂一个属性,属性名就叫svn:eol-style。

先分清楚几个值,选错了效果完全不一样。

native,仓库统一存 LF,检出时按平台转换。Windows 上检出成 CRLF,Linux 和 Mac 检出成 LF。适合「每个平台用自己习惯的行尾」的团队。

LF,仓库存 LF,检出也永远是 LF,在 Windows 上也是 LF。适合「行尾就统一成 LF,谁也别转」的团队。

我要的是后一种,所以选 LF。方向定了就是全项目 LF,不要再让平台转换插一脚。

怎么设。四种方式,从最直接的到最省事的。

方式一,图形界面。在要处理的文件夹上右键,TortoiseSVN,Properties,New,eol-style,选 LF,勾上「Set property recursively」,确定。适合只改一两个目录。

方式二,命令行按目录递归。一行就够。

svn propset svn:eol-style LF --recursive Assets

svn propset svn:eol-style LF --recursive .

这里有个容易误解的点。SVN 的属性不继承。--recursive是把每个文件挨个设一遍,不是「给文件夹设了,子文件就自动有」。文件夹上挂属性,不会传给里面的文件。

方式三,命令行按清单批量。如果只想处理某类文件,还要避开第三方目录,先生成一份清单再喂给它。

svn list -R > all-files.txt

svn propset svn:eol-style LF --targets cs-list.txt

第一行把受版本控制的文件全列出来。编辑这份清单,只留 .cs,把Plugins/下面的删掉,存成 cs-list.txt。--targets后面就是一个一行一个路径的文本文件。我就是这么只给版本化的 .cs 设的属性,第三方插件一个没动,别人的代码别去改。

方式四,auto-props,让新文件自动带上。前面三种只管现有文件,之后新加的文件属性还是空的。在本机的 Subversion config 里加两段,新文件一svn add就自动带上。

[miscellany]

enable-auto-props = yes

[auto-props]

*.cs = svn:eol-style=LF

*.csproj = svn:eol-style=LF

*.bat = svn:eol-style=CRLF

*.cmd = svn:eol-style=CRLF

config 文件在 Windows 上一般在%APPDATA%\Subversion\config。改完对之后新加的文件生效。

这里有两个坑。一是enable-auto-props = yes不打开,下面的 auto-props 根本不生效,这个最常见。二是 auto-props 只对之后新增的文件起作用,已经入库的老文件得靠前面三种方式手动补。

设完别忘了提交。propset 只改了你的工作副本,属性本身也是受版本控制的。要让团队其他人都拿到,得svn commit一次。

怎么确认真的设上了。查单个文件,用 propget 加属性名和文件路径。想给整个目录体检,加--recursive,它会逐个列出路径和属性值,没设的显示 none。

svn propget svn:eol-style Assets/Scripts/Player.cs

svn propget svn:eol-style --recursive Assets

顺手再看一眼svn status。属性变更和内容变更在输出里占的是两列,别搞混。

MM Assets/Scripts/Player.cs

M Assets/Scripts/Player.cs

第一列是内容状态,第二列是属性状态。MM 是内容和属性都变了。前面空一格、只有一个 M 的,是只改了属性。我第一次看的时候就没分清这两列。

设错了想撤销,把 propset 换成 propdel,一行删掉。

svn propdel svn:eol-style --recursive Assets

改成 LF 之后,SVN 还能 diff 出差异吗

这是我最关心的问题。我先拿一个文件做了次受控实验,结论分两层。



第一层,只改行尾,SVN 会不会认为文件变了。答案取决于有没有设 svn:eol-style。

没设的时候,SVN 是按行比较的,行尾符号也算在这一行里。你把整份文件的 CRLF 换成 LF,在它眼里就是每一行都变了,diff 变成整份删除加整份重新添加。几百行假差异,真正改的那几行得在噪声里捞。

设了之后,SVN 比较的是归一化之后的内容。纯行尾的变化被它吃掉了,不再产生 diff。只有你真正改过的行才会出现。

所以加 svn:eol-style 最大的好处,不是「能 diff」,而是让 diff 干净。它把行尾这一类噪声永久性地从 diff 里删掉了。

第二层,那设置属性本身,会不会造成一次全文件改动。可能会,而且这是必须付的一次性代价。

如果你的文件在仓库里存的是 CRLF,属性却要求 LF,那这次提交会让整个文件看起来被改了。这是一次性代价,吃掉它就好。

正确的做法是三步。第一步,把要改的文件挑出来,设属性、顺手把内容归一化。第二步,就这一次,单独提交,提交信息写明「纯格式变更,无逻辑改动」。第三步,之后正常写代码,diff 里只剩你真正动过的那几行。

关键在第二步。格式变更必须单独一条提交,不能和功能改动混在一起。混在一起,你以后想单独回滚这次格式变更都做不到。

总结经验

在AI时代里,编码和行尾的变化问题是值得重视的,与手写时代的默认值不同了。

非常建议加上.editorconfig /.gitattributes /svn:eol-style这3个设置,至于怎么写怎么加,找AI搞就行,只不过你不说,AI就不会去做。

声明:内容由AI生成

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
中央依法治国办启动领导干部依法办事情况法治督察

中央依法治国办启动领导干部依法办事情况法治督察

界面新闻
2026-10-14 09:39:13
公园洗手池排水孔突然钻出一条蛇,当事人:当时正洗手,蛇突然探出头来吓了一跳;工作人员:发现蛇会捕捉放生

公园洗手池排水孔突然钻出一条蛇,当事人:当时正洗手,蛇突然探出头来吓了一跳;工作人员:发现蛇会捕捉放生

扬子晚报
2026-10-15 09:27:17
WTT大满贯决赛「闪光灯门」掌镜者竟是中华队选手!球团今致歉

WTT大满贯决赛「闪光灯门」掌镜者竟是中华队选手!球团今致歉

ETtoday星光云
2026-10-14 17:15:28
“龃龉”不读 zǔ wú!也不读 jū chǐ!我出过丑太丢人!

“龃龉”不读 zǔ wú!也不读 jū chǐ!我出过丑太丢人!

语丝纪
2026-10-15 07:45:07
没辜负穆帅:居莱尔替补导演3球,助皇马4-3大逆转,现场视角还原,太牛了

没辜负穆帅:居莱尔替补导演3球,助皇马4-3大逆转,现场视角还原,太牛了

侧身凌空斩
2026-10-15 06:34:13
越南网友拿出古地图,想证明西沙南沙属于越南,结果证明越南古代属于中国

越南网友拿出古地图,想证明西沙南沙属于越南,结果证明越南古代属于中国

世界纵横说
2026-09-21 11:36:25
Model Y,已经“无法无天”了……

Model Y,已经“无法无天”了……

小李车评李建红
2026-10-15 09:54:15
“书包都是四位数!”小学女孩上学照火了,网友:你奋斗一辈子都买不起这种车

“书包都是四位数!”小学女孩上学照火了,网友:你奋斗一辈子都买不起这种车

蝴蝶花雨话教育
2026-10-15 00:05:14
震惊!上海通用别克的产品发布会上,用刹车踏板做背景板,打出“别克造车不允许一点水分”的口号

震惊!上海通用别克的产品发布会上,用刹车踏板做背景板,打出“别克造车不允许一点水分”的口号

火山詩话
2026-10-12 20:15:00
法比奥:我想对林良铭说,需要快点把合同续约了

法比奥:我想对林良铭说,需要快点把合同续约了

懂球帝
2026-10-14 14:51:36
意大利前经济发展部副部长嘲讽中国!指责中国铁路太过准点,搞得大家不懂选择

意大利前经济发展部副部长嘲讽中国!指责中国铁路太过准点,搞得大家不懂选择

小徐讲八卦
2026-10-14 07:01:47
《伟大的长征》李德的指挥,为什么如此荒唐?日常生活说明一切

《伟大的长征》李德的指挥,为什么如此荒唐?日常生活说明一切

天玑影视说
2026-10-14 12:41:33
全球手机出货量暴跌 20%!最新排名:三星第一、华为未进前五!

全球手机出货量暴跌 20%!最新排名:三星第一、华为未进前五!

EETOP半导体社区
2026-10-13 12:49:37
日本人有句话评价抗美援朝,让人后背发凉:“中国若是不出兵,美国根本打不到鸭绿江边。可中国偏偏去了。

日本人有句话评价抗美援朝,让人后背发凉:“中国若是不出兵,美国根本打不到鸭绿江边。可中国偏偏去了。

回京历史梦
2026-10-12 09:12:01
再砍17+10+6+4!雷霆神塔彻底打疯,文班和约基奇该慌了

再砍17+10+6+4!雷霆神塔彻底打疯,文班和约基奇该慌了

哄动一时啊
2026-10-15 10:04:29
她曾睡遍才子大佬,前半生阅男无数,晚年无人陪伴,如今独居广州

她曾睡遍才子大佬,前半生阅男无数,晚年无人陪伴,如今独居广州

铜臭的历史味
2026-10-13 11:28:57
王星在诈骗园区被胁迫借下网贷,最终选择分期偿还,律师:王星如举证证实案涉网贷合同系受胁迫订立,有权诉请法院撤销借贷合同

王星在诈骗园区被胁迫借下网贷,最终选择分期偿还,律师:王星如举证证实案涉网贷合同系受胁迫订立,有权诉请法院撤销借贷合同

都市快报橙柿互动
2026-10-14 21:21:20
知名演员谭耀文今日公开发文怒斥:这个人根本就是可恶人渣!

知名演员谭耀文今日公开发文怒斥:这个人根本就是可恶人渣!

小椰的奶奶
2026-10-15 00:48:55
宋佳的幸福,从来不是轰轰烈烈的官宣

宋佳的幸福,从来不是轰轰烈烈的官宣

松林侃世界
2026-10-15 06:55:00
胡塞武装,凭什么这么难打?因为坚决不建国,因为借鉴中国游击战

胡塞武装,凭什么这么难打?因为坚决不建国,因为借鉴中国游击战

烈史
2026-09-24 10:27:55
2026-10-15 11:00:49
刘俊亨of游戏开发者 incentive-icons
刘俊亨of游戏开发者
游戏开发者,游戏鉴赏家,怀旧游戏玩家
85文章数 585关注度
往期回顾 全部

科技要闻

国行苹果AI被曝12月上线,新Siri仍要等

头条要闻

著名女星被逮捕 飞机上拳击撕咬空乘企图强开舱门

头条要闻

著名女星被逮捕 飞机上拳击撕咬空乘企图强开舱门

体育要闻

30天30队·开拓者:利拉德?莫兰特?

娱乐要闻

陈小春弟弟被卖,多年不打扰另有隐情

财经要闻

洋餐饮的中国生意:红利消退后的集体交权

汽车要闻

不止大空间/纯电增程任选 小鹏MONA L05来了

态度原创

艺术
游戏
健康
手机
公开课

艺术要闻

天凉了,叶黄了,秋来了……

魔兽世界:历史记忆感最强的传奇匕首,见过第一款才是真大佬!

孩子运动莫名晕倒?当心这类疾病

手机要闻

国行版苹果智能即将上线 12月iOS 26.3系统更新

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版