一文搞懂换行符(CRLF & LF)并在项目规范使用

2023年 8月 15日 20.7k 0

背景

换行符的问题很容易被人忽视,但是如果你要在项目中对代码格式进行规范化的时候就不得不重视它了。换行符的问题主要影响window系统用户。例如以下场景

  • git add时会有一个警告(当本地修改的文件换行符是LF时)
  • git add .
    warning: in the working copy of '.eslintrc.cjs', LF will be replaced by CRLF the next time Git touches it
    
  • 当项目中有使用EsLint校验并指定了换行符时,无法同时兼容Mac和Window系统。
    • 如果设置为CRLF,Mac系统中默认是LF,EsLint则会有警告。
    • 如果设置为LF,Window系统中默认是CRLF,EsLint同样会有警告。

    CRLF 和 LF说明

    要想理解LF和CRLF,需要先理解CR和LF

    • CR(CarriageReturn)代表回车,对应\r :回到一行的开头,ASCII代码是13
    • LF(LineFeed)代表换行,对应字符\n:另起一行,ASCII代码是10

    在不同的操作系统和环境中,CR和LF的组合用于实现换行

    • Windows 和 Dos系统: 使用回车(CR)和换行(LF)两个字符来结束一行,回车+换行(CR+LF),即“\r\n”;所以我们平时编写文件的回车符应该确切来说叫做回车换行符。
    • Mac 和 Linux系统:只使用换行(LF)一个字符来结束一行,即“\n”;现代的版本控制系统(如:git)中也使用LF表示换行。

    CR 和 LF 的历史(来自ChatGPT)

  • CR(Carriage Return) : CR是一个控制字符,通常用来将光标移动到行的起始位置,而不换行。它最初来自于打字机时代,打字机中的"回车"操作会将打印头移动到左侧并保持在同一行上。在计算机中,CR通常用来表示光标回到当前行的起始位置,但不会移动到下一行。
  • LF(Line Feed) : LF是另一个控制字符,用于将光标移动到下一行的起始位置,实现真正的换行。在计算机中,LF会使光标移到下一行,并定位在左侧,从而开始新的一行。
  • Git的换行符处理

    core.autocrlf

    通过core.autocrlf可以更改git处理换行符的方式。

    core.autocrlf有三个值:

  • 当设置为true时,git提交代码时会自动将CRLF转换为LF,在检出代码时会将LF转换成CRLF。一般在windows上使用该功能。
  • git config --global core.autocrlf true
    
  • 在Linux或MacOS上时,使用LF作为换行符,检出代码时不需要转换。但是当代码中已有一个CRLF换行符时,在提交时就需要将其转换成LF。因此input的功能是在提交代码时,将CRLF转换成LF;检出代码时不转换。
  • git config --global core.autocrlf input
    
  • 当设置成false时,表示不做任何转换。因此可以把CRLF提交到版本库中。
  • git config --global core.autocrlf false
    

    综上,如果是跨平台开发和运行,core.autocrlf应在windows上设置为true(windows中默认为true),在Linux和MacOS上设置为input;如果仅在windows上开发和运行的项目,可以设置为false

    core.safecrlf

    当值为true时,如果你的代码中同时包含两种不同的换行格式会被禁止提交。默认为false。

    # 不允许提交包含混合换行符的文件
    git config --global core.safecrlf true
    
    # 允许提交包含混合换行符的文件
    git config --global core.safecrlf false
    
    # 提交包含混合换行符的文件时给出警告
    git config --global core.safecrlf warn
    

    core.eol

    eol 表示 "end of line",即"行尾"的意思。当core.autocrlffalse时可以设置文本文件的换行符类型。有三个值crlflfnative,默认是native,表示平台默认的换行符。

    最好的解决方案

    以上方式虽然能解决问题,但是必须要所有项目参与者都在本地设置git,可操作性不太,容易有遗漏。最好是能在项目中进行设置,这样子才能保证所有参与者是一致的。通过.gitattribute文件配置就能很好地解决这个问题。 将此文件提交到存储库时,它将覆盖所有开发者本地的设置(如:core.autocrlf)。 这可确保所有用户的行为一致,而不管其 Git 设置和环境如何。

    .gitattribute

    通过.gitattribute文件配置仓库的git是更好的方式。

    常用的配置:

    * text=auto eol=lf
    

    *匹配所有文件,text=auto表示由git自己识别是否是文本文件(因为二进制文件,如图片,不需要转换换行符),eol=lf将换行符设置为LF。

    使用了.gitattribute则不需要设置core.autocrlfcore.eol,因为.gitattribute中的配置优化级更高。

    添加以上文件和配置内容后,当前分支并的文件并不会更新成配置的方式。只有重新git clone代码时文件换行符格式才会以配置的方式展示。

    若要以.gitattribute文件中配置的换行符更新当前分支上的所有文件,请运行以下命令。

    git rm -rf --cached .
    git reset --hard HEAD
    

    如果不小心将CRLF换行符提交到仓库,则可以通过以下命令修复,然后重新提交。

    git add --renormalize .
    

    EsLint指定换行符的方式

    正常按以上操作后即可。如果想要明确指定换行符,可以按以下方式设置。

    1. 只有EsLint时,设置EsLint规则。

    module.exports = {
        // ...
        rules: {
            // ...
            'linebreak-style': ['error', 'unix'] // unix表示LF,windows表示CRLF。
        }
    }
    

    2. EsLint + Prettier时,设置Prettier规则。

    module.exports = {
        // ...
        endOfLine: 'auto' // lf:"\n"; crlf:"\r\n"; auto: 兼容两者;
    }
    

    在Prettier配置文件中指定换行符方式,使用Prettier的格式化功能。也是一个不错的统一处理换行符的方式。

    参考文献

    • 规范处理项目中的换行符(CRLF & LF)
    • 配置 Git 处理行结束符

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论