在github上面向别人的项目代码pull request的时候遇到了一个蛋疼的问题,问题都在一个字符上面就是^M,我的代码虽然只修改了几行代码,但是使用git diff的时候发现整个文件全部修改了。


原因就是我修改的文件在每一行末尾都新增了一个^M字符,这样就导致每一行都和以前不同diff的时候自然就全部不同了,这样就非常的蛋疼,向别人项目中pull request的时候一整片红色和一整片绿色,别人包括我自己都不知道我到底是修改的哪一部分,感觉像是在捣乱的。。。像这样的pull request人家才不会给我merge呢。


真是太不好意思了,诶…效果就是这蛋疼的下图:


那造成这种的原因是什么呢?

原因就是我用的是windows而写项目的人是使用的*nix。在一般的C语言入门书里的关于I/O的章节中应该都有写过,就是Windows和*nix的文本文件中的换行符是不同的。


在Windows中:使用\r\n来标志换行的,也就是所谓的CR TF,其中CR的全称是Carriage Return ,或者表示为\r, 意思是回车。LF全称是Line Feed,它才是真正意义上的换行表示符。
在Linux中:使用的只有\nLF来表示换行。

这样我在Windows下修改的文件在每次换行的时候都会有一个多余的\r了。


如何解决这个问题?

在github官网有针对这个问题的解决方案:https://help.github.com/articles/dealing-with-line-endings/
使Git在git diff的时候能够忽略操作系统之间换行符的差异。

总结起来就是两个方法:

  1. 全局设置
    使用git config core.autocrlf来告诉Git如何处理行尾的换行符

    1
    2
    $ git config --global core.autocrlf true
    # Configure Git on Windows to properly handle line endings
  2. 针对某个项目而不是全局设置
    这样就需要在项目的根目录中添加.gitattributes文件,在文件中配置当前项目。
    关于.gitattributes文件的格式,官网有解释,就好象是包含了两列的列表,第一列是Git需要匹配的文件名称,第二列是配置参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # Set the default behavior, in case people don't have core.autocrlf set.
    * text=auto

    # Explicitly declare text files you want to always be normalized and converted
    # to native line endings on checkout.
    *.c text
    *.h text

    # Declare files that will always have CRLF line endings on checkout.
    *.sln text eol=crlf

    # Denote all files that are truly binary and should not be modified.
    *.png binary
    *.jpg binary

    左边是文件名称:*.c, *.sln, *.png
    右边是配置参数:text, text eol=crlf, binary

Comments