通过阅读git-config文档理解Git如何使用autocrlf、safecrlf、eol和.gitattributes处理line-ending

[toc]

一、遇到的问题

在Windows平台上,会出现如下的warning:

$ git add app.wxss
warning: LF will be replaced by CRLF in app.wxss.
The file will have its original line endings in your working directory.

为什么会出现这个warning呢?

二、为什么会出现这个问题

通过查阅《ProGit》的相关内容,可以得知:

If you’re programming on Windows and working with people who are not (or vice-versa), you’ll probably run into line-ending issues at some point. This is because Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas Mac and Linux systems use only the linefeed character. This is a subtle but incredibly annoying fact of cross-platform work; many editors on Windows silently replace existing LF-style line endings with CRLF, or insert both line-ending characters when the user hits the enter key.
简单翻译一下,Windows在换行的时候,同时使用了回车符(carriage-return character)和换行符(linefeed character);而Mac和Linux系统(很老的mac系统才是CR,可以参见wiki),此时,仅仅使用了换行符(linefeed character)。同时呢,Windows的许多编辑器还悄悄滴将LF修改成了CRLF格式的行结束符,或者在你敲回车的时候,CRLF格式的行结束符就产生了。当然,这一切都发生在同时存在Windows和非Windows的跨平台工作中,如果大家都是同一种操作系统,那么,就天下太平了。

warning中所说的LF和CRLF分别是linefeed和carriage-return&linefeed。
那么现在,再仔细看warning的内容,为什么在git add的时候,“警告:app.wxss中的LF将来会被替换成CRLF”?

三、为什么LF->CRLF

Git can handle this by auto-converting CRLF line endings into LF when you add a file to the index, and vice versa when it checks out code onto your filesystem.
Git有一个针对性的功能:当添加到暂存区时,自动将CRLF转换成LF;反之,当检出时,自动将LF转换成CRLF。
You can turn on this functionality with the core.autocrlf setting.
可以通过设置core.autocrlf来开启这个功能。

看到这里,就更加不懂了,添加到暂存区时,为什么警告LF将被转换成CRLF?这不是和功能相反了吗?

四、原因

这个问题与git-config里面的相关设置有关,主要涉及到三个参数:

  • core.autocrlf
  • core.safecrlf
  • core.eol

这三个参数用来配置Git处理line-ending的方式。

五、接下来,来看如何配置

1. core.autocrlf

(1) true

If you’re on a Windows machine, set it to true — this converts LF endings into CRLF when you check out code:
$ git config --global core.autocrlf true
如果是在 Windows 系统上,把它设置成 true,这样在检出代码时,换行(LF)会被转换成回车和换行(CRLF)

(2) input

If you’re on a Linux or Mac system that uses LF line endings, then you don’t want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. You can tell Git to convert CRLF to LF on commit but not the other way around by setting core.autocrlf to input:
$ git config --global core.autocrlf input
如果使用以换行作为行结束符的 Linux 或 Mac,你不需要 Git 在检出文件时进行自动的转换;然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把 core.autocrlf 设置成 input 来告诉 Git 在提交时把回车和换行转(CRLF)换成换行(LF),检出时不转换

(3) false

If you’re a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to false:

$ git config --global core.autocrlf false

如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 false 取消此功能,把回车(CR)保留在版本库中

以上,是core.autocrlf的设置规则与建议。

2. core.safecrlf

通过查阅git-scm上的文档上关于git-config的文档或者mirrors.edge.kernel.org

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.

简单翻译一下:当core.autocrlftrue或者input时,算激活了eol,此时如果core.safecrlftrue,Git检查crlf转换是否正常,比如Windows平台,core.autocrlf设置为true,如果工作区的文件中含有LF,Git就会拒绝,因为true的情况下,Git认为工作区应该都是CRLF才对啊

给你一个致命大礼,fatal:LF would be replaced by CRLF in app.wxss.,阻止你继续操作。


^ _ ^ 使用dos2unix进行手动转换

这种情况不要慌,可以使用dos2unix工具中的unix2dos将LF转换成CRLF,来满足core.autocrlftrue的要求。当然,解决的方法有很多,可以根据实际情况,使用不同的方法来解决。
以下命令可以将当前文件夹内的文件批量的转换,也有其他方式,比如find . -type f -exec dos2unix {} +,可以自行Google

find . -type f -print0 | xargs -0 dos2unix

dos2unix工具在Windows的MINGW64 Git Bash客户端上自带,在mac平台可以Google how to install dos2unix on mac,同理linux(sudo apt-get install dos2unix),哈哈哈。


The variable can be set to "warn", in which case Git will only warn about an irreversible conversion but continue the operation.
也可以设置core.safecrlfwarn,Git就只会警告一下,不会阻止你。

继续看文档的内容。写着写着成了《带你看文档系列》了,所以很多问题,仔细看文档就能解决,但是文档太多,也很难看懂,只能花时间多看了。

CRLF conversion bears a slight chance of corrupting data. When it is enabled, Git will convert CRLF to LF during commit and LF to CRLF during checkout. A file that contains a mixture of LF and CRLF before the commit cannot be recreated by Git. For text files this is the right thing to do: it corrects line endings such that we have only LF line endings in the repository. But for binary files that are accidentally classified as text the conversion can corrupt data.
If you recognize such corruption early you can easily fix it by setting the conversion type explicitly in .gitattributes. Right after committing you still have the original file in your work tree and this file is not yet corrupted. You can explicitly tell Git that this file is binary and Git will handle the file appropriately.

这一段主要是说,同时有LFCRLF的文件是被腐蚀的,这类文件是不被Git认可的,而CRLF的转换过程很可能会产生腐蚀的文件,比如二进制的文件被当作文本的话,就会被腐蚀。

所以提出了重要的文件.gitattributes来明确转换配置,而且越早设置越好。你可以明确地指出某些文件是二进制的,比如*.jpg,Git知道了以后,会妥善处理。

Note, this safety check does not mean that a checkout will generate a file identical to the original file for a different setting of core.eol and core.autocrlf, but only for the current one. For example, a text file with LF would be accepted with core.eol=lf and could later be checked out with core.eol=crlf, in which case the resulting file would contain CRLF, although the original file contained LF. However, in both work trees the line endings would be consistent, that is either all LF or all CRLF, but never mixed. A file with mixed line endings would be reported by the core.safecrlf mechanism.

我的理解是,A和B协同开发,A设置的是core.eol=lf core.autocrlf=true,B设置的是core.eol=crlf core.autocrlf=true,那么A checkout的时候,生成lf结尾的文件,而B checkout的时候,生成crlf结尾的文件。要么都是lf,要么都是crlf安全检查不可能允许混合出现,如果发现了混合的行结束符,就会报警

3. core.eol

通过查阅git-scm上的文档上关于git-config的文档或者mirrors.edge.kernel.org

Sets the line ending type to use in the working directory for files that have the text property set when core.autocrlf is false. Alternatives are lf, crlf and native, which uses the platform’s native line ending. The default value is native. See gitattributes[5] for more information on end-of-line conversion.
core.autocrlffalse,设置行结束符的类型,可以是

  • lf
  • crlf
  • native三种,其中native是指平台默认的行结束符。默认的类型是native

欲知详情,请翻阅gitattributes[5]或者mirrors.edge.kernel.org

六、总结一下吧

1. 不安全不保险的方式

虽然Google查询LF will be replaced by CRLF,几个答案会建议设置

git config --global core.autocrlf false
git config --global core.safecrlf false

比如stackoverflow知乎github上的bolg中的某些答案(这几个链接里也是有一些干货的),
但是,通过上面我们看文档的过程,我们发现这种方式,是不保险的。很容易产生混合,git diff的时候,就会影响我们查看版本之间的修改。

2. 个人推荐的设置方式

(1)添加.gitattributes

首先要在项目里添加.gitattributes文件,可以参考Github help-Dealing with line endingsgitattributes[5],这是我自己的.gitattributes

(2)safecrlf设置为true

git config --global core.safecrlf true

(3)autocrlf在不同平台不同设置

  • Windows
git config --global core.autocrlf true
  • Mac Or Linux
git config --global core.autocrlf input

(4)eol默认native,因为autocrlf不是false,也不起作用啊

补充

第一点 Git Setup Treat Line Endings In Text Files

Git默认的core.autocrlf其实在安装Git For Windows的时候,让我们选择了,只是安装的时候并不会注意,就是下面这张图:

Git treat line endings in text files

由上向下依次是true input false

第二点 TortoiseGit settings about AutoCrlf

另外,如果使用的是TortoiseGit,要注意其中的设置:


TortoiseGit settings
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容

  • git 使用笔记 git原理: 文件(blob)对象,树(tree)对象,提交(commit)对象 tree对象 ...
    神刀阅读 3,714评论 0 10
  • 良好的配置有助于提高效率,减少不必要的错误。把运行配置的相关内容单拎出来放到这里,查找和更新方便。 Customi...
    michael_jia阅读 20,445评论 1 10
  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 8,586评论 0 23
  • 日下成影 逆风独行 对月当空 凝思顿挫 惊霎之间 人生几何 不知方圆 如若地方 路间设坷 虽有险峻 但求华丽 如若...
    虹帆阅读 366评论 0 8
  • 第一:在不能了解客户的真实问题时,尽量让客户说话 多打听一些问题,带着一种好奇的心态,发挥刨根问底的精神,让客户多...
    思念的诗阅读 169评论 0 0