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

[原文链接:通过阅读 git-config 文档理解 Git 如何使用autocrlf、safecrlf、eol和.gitattributes处理line-ending](https://xiaozhuanlan.com/topic/4053786912#sectionlfcrlf)

# 一、遇到的问题

在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》的相关内容](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#Formatting-and-Whitespace),可以得知:

```

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](https://git-scm.com/docs/git-config)上的文档上关于`git-config`的文档或者[mirrors.edge.kernel.org](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html)

```

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.autocrlf`为`true`或者`input`时,算激活了`eol`,此时如果`core.safecrlf`为`true`,Git检查`crlf`转换是否正常,比如Windows平台,`core.autocrlf`设置为`true`,如果工作区的文件中含有`LF`,Git就会拒绝,因为true的情况下,Git认为工作区应该都是`CRLF`才对啊。

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

---

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

这种情况不要慌,可以使用[dos2unix](https://waterlan.home.xs4all.nl/dos2unix.html)工具中的unix2dos将`LF`转换成`CRLF`,来满足`core.autocrlf`为`true`的要求。当然,解决的方法有很多,可以根据实际情况,使用不同的方法来解决。

以下命令可以将当前文件夹内的文件[批量的转换](https://stackoverflow.com/questions/11929461/how-can-i-run-dos2unix-on-an-entire-directory),也有其他方式,比如`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](http://macappstore.org/dos2unix/),同理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.safecrlf为warn,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.

```

这一段主要是说,同时有`LF`和`CRLF`的文件是被腐蚀的,这类文件是不被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](https://git-scm.com/docs/git-config)上的文档上关于git-config的文档或者[mirrors.edge.kernel.org](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html)

```

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.autocrlf是false时,设置行结束符的类型,可以是

lf

crlf

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

```

欲知详情,请翻阅[gitattributes[5]](https://git-scm.com/docs/gitattributes)或者[mirrors.edge.kernel.org](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/gitattributes.html)。

# 六、总结一下吧

## 1. 不安全不保险的方式

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

```

git config --global core.autocrlf false

git config --global core.safecrlf false

```

比如[stackoverflow](https://stackoverflow.com/questions/5834014/lf-will-be-replaced-by-crlf-in-git-what-is-that-and-is-it-important),[知乎](https://www.zhihu.com/question/50862500/answer/123197258),[github上的bolg](https://github.com/cssmagic/blog/issues/22)中的某些答案(这几个链接里也是有一些干货的),

但是,通过上面我们看文档的过程,我们发现这种方式,是不保险的。很容易产生混合,git diff的时候,就会影响我们查看版本之间的修改。

## 2. 个人推荐的设置方式

### (1)添加.gitattributes

首先要在项目里添加.gitattributes文件,可以参考[Github help-Dealing with line endings和gitattributes[5]](https://help.github.com/articles/dealing-with-line-endings/),这是我自己的[.gitattributes](https://github.com/ThorWu/running_pomelo/blob/master/.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](https://camo.githubusercontent.com/c334a5644f69da294255a1de0a690239f8a83131/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313233313335392f3937343134392f64396564313662652d303634622d313165332d393336382d3831373138616563653335322e706e67)

由上向下依次是`true input false`。

#### 第二点 TortoiseGit settings about AutoCrlf

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

![TortoiseGit settings](https://camo.githubusercontent.com/8d6a7962aba0ce4e94ec32e4bf788360a84b301f/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313233313335392f3937343136322f31363930353264342d303634632d313165332d393434352d3535656637303238623633632e706e67)

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

推荐阅读更多精彩内容