Git CRLF LF EOL转换设置

时间:2014-11-18 09:41:16

标签: git emacs core.autocrlf

平台:Windows 8.1 Emacs 24.3

git config --global -l显示:

user.name=username
user.email=useremail
core.autocrlf=false
core.safecrlf=true

Git存储库.gitattributes文件:

# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp
*.sln    merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc    diff=astextplain
*.DOC    diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF    diff=astextplain
*.rtf    diff=astextplain
*.RTF    diff=astextplain

我认为我的Git和存储库设置是正确的。

但每次我使用Emacs创建一个新的文本文件时,我都无法运行git add <newfile>。该文件由utf-8-unix编码。

错误消息如下:

E:\workspace\repository [master +0 ~2 -0]> git add .
fatal: LF would be replaced by CRLF in newfile.txt

我不认为是由于emacs编辑器问题。因为我打开了新文件,并且非常确定行结尾是LF,而不是Windows默认CRLF

哪个配置部分决定LF将被CRLF替换?


编辑1
如果safecrlf设置为warn,则输出为:

warning: LF will be replaced by CRLF in _posts/2014-11-19-test.md.
The file will have its original line endings in your working directory.

这意味着该文件已成功添加到索引中。我的文件由utf-8-unix编码。


编辑2

有趣的是,如果我用记事本而不是Emacs 24.3创建一个新文件,则可以毫无问题地添加该文件。区别在于记事本采用CRLF行结束,而Emacs 24.3采用LF行结束。

所以问题就在某处Git将CRLF转换为LF然后转回CRLF,这会为原始LF行结束文件生成错误。


编辑3

以前,GitHub Windows GUI客户端警告我没有.gitattributes我的存储库文件,并建议如上所述的默认.gitattributes文件。

我认为问题来自* text=auto行。所以我评论了这一行。

现在一切都很好!


编辑4

核心是:

    GitHub
  • 禁用自动线结束转换

  • 依赖平台文件编辑器结束


编辑5

  1. text 此属性启用并控制行尾标准化。对文本文件进行规范化后,其行结尾将转换为存储库中的LF 。要控制在工作目录中使用的行结尾样式,请使用eol属性表示单个文件,并使用core.eol配置变量对于所有文本文件
    • 在路径上设置text属性可启用行尾标准化,并将路径标记为文本文件。行结束转换发生在而不猜测内容类型
    • 取消设置路径上的text属性会告知Git 在签入或结帐时不会尝试任何行尾转换
    • text设置为&#34; auto&#34;时,路径会标记为自动行结束规范化。如果 Git决定内容为文本,则其行结尾会在签入时标准化为 LF
    • 未指定。如果text属性未指定(通过!text或根本没有设置条目),Git使用core.autocrlf配置变量来确定是否应该转换文件(如下所述的后备兼容性)在 编辑8 )。
  2. eol 此属性设置要在工作目录中使用的特定行结束样式。它可以在没有任何内容检查的情况下实现行尾标准化,有效地设置text属性
    • 也就是说eol会自动设置text属性
    • 设置为字符串值&#34; crlf&#34;
      此设置强制Git在签入时规范化此文件的行结尾,并在签出文件时将其转换为CRLF。
    • 设置为字符串值&#34; lf&#34;
      此设置强制Git在签入时将行结尾标准化为LF,并在签出文件时阻止转换为CRLF。
  3. 如果eol放在.gitattributes文件中,则应将其应用于特定文件类型。同时,它会在签入时自动将特定文件类型标记为text,以便进行LF规范化。如果将eol设置为git config --global core.eol xxx,则会为所有文本文件设置eol

    请参阅gitattributes - defining attributes per path


    编辑6

    Git属性在.gitattributes个文件中指定。行结尾由texteol属性控制。

    text属性告诉Git文件是否为binary(即在结帐时不应执行EOL转换)或text(执行EOL转换,在检入时始终转换为LF。设置了可能的值(EOLs转换已打开),未设置(EOLs转换已关闭,默认值)和auto(如果文件被检测为二进制,无转换,否则执行EOL转换)。

    eol属性:如果设置隐式设置text属性,则定义在签出时应将文件转换为的EOL。

    请参阅Line endings handling in SVN, Git and SubGit


    编辑7

    可能的解决方案:

    1. 作为 编辑3 ,请注释掉* text=auto
    2. gitattributes文件的.md中添加一行:*.md eol=lf
      • 如果创建了其他类型的文本文件,例如.txt,我还应为其添加一行*.txt eol=lf
    3. * text=auto更改为* !text
    4. 完全删除.gitattributes文件
    5. 据我所知,我认为:

      1. filetype textgitattributes,在签到时对filetype执行EOL规范化。
      2. 在同一时间,这一行暗示在结账时也应执行default eoldefault表示全局配置为git config --global core.eol xxx或默认操作系统样式为core.eol = native
        • 您可以运行git config --global core.eol以查看系统上此值的设置。如果没有任何反馈意味着您正在使用操作系统默认值native
      3. eol暗示text属性,而text暗示默认eol属性
      4. 因此启用*.md text=auto时。 Git将*.md文件检测为text文件,并在签入时转换为LF。结账时,*.md LF将转换为CRLF。此过程由safecrlf = false全局设置无效,拒绝将文件添加到索引/阶段区域。

      5. 编辑8

        我在 编辑7 中的三个假设已经过验证Mind the End of Your Line

        从Git 1.7.2及更高版本开始,EOL设置主要放在工作树根目录下的.gitattributes中。全局配置autocrlf仅用于后备兼容性。

        *.txt text将与过滤器*.txt匹配的所有文件设置为text。这意味着Git每次将这些文件写入对象数据库时都会对这些文件进行CRLFLF替换,并且在写入工作目录时将运行反向替换


        编辑9最终想法

        1. textcore.autocrlf(在.gitattributes中)专注于从工作树写入存储库数据库的EOL转换。
        2. eolcore.eol(在global config中)专注于从存储库数据库写入工作树的EOL转换。
        3. 在决定EOL转换时,
        4. .gitattributes的优先级高于global config。后者实际上是后备参考。
        5. 如果指定了单向转换,则另一种方式未指定或未定义,默认的后退选项用于其他方式转换。
        6. EOL问题与您在编辑文件时选择的行结束密切相关。
        7. 有关合理解释,请参阅我的博客znhoo

2 个答案:

答案 0 :(得分:0)

罪魁祸首是Git配置中的core.safecrlf=true

来自the git-config manual page

core.safecrlf
    If true, makes git check if converting CRLF is reversible when
    end-of-line conversion is active. Git will verify if a command
    modifies a file in the work tree either directly or indirectly. For
    example, committing a file followed by checking out the same file
    should yield the original file in the work tree. If this is not the
    case for the current setting of core.autocrlf, git will reject the
    file. The variable can be set to "warn", in which case git will only
    warn about an irreversible conversion but continue the operation.

答案 1 :(得分:0)

可能的解决方案:

  1. 作为 编辑3 ,请注释掉* text=auto
  2. gitattributes文件的.md中添加一行:*.md eol=lf
    • 如果创建了其他类型的文本文件,例如.txt,我还应为其添加一行*.txt eol=lf
  3. * text=auto更改为* !text
  4. 完全删除.gitattributes文件