距离我提出这个问题已经将近四年,我终于找到一个完全让我满意的答案!
具体详情请参见github:help中关于处理换行符的指南。
Git允许您直接使用
.gitattributes
文件中的text属性为存储库设置行尾属性。该文件被提交到存储库并覆盖了core.autocrlf
设置,确保所有用户的行为都是一致的,而不管他们的git设置如何。
因此
这样做的好处是,您的行尾配置现在可以随着您的存储库一起传输,您不需要担心协作者是否具有正确的全局设置。
这里是一个.gitattributes
文件的示例:
# Auto detect text files and perform LF normalization
* text=auto
*.cs text diff=csharp
*.java text diff=java
*.html text diff=html
*.css text
*.js text
*.sql text
*.csproj text merge=union
*.sln text merge=union eol=crlf
*.docx diff=astextplain
*.DOCX diff=astextplain
# absolute paths are ok, as are globs
/**/postinst* text eol=lf
# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf
有方便的准备好的 .gitattributes 文件集合可供最流行的编程语言使用。这对于入门非常有用。
一旦您创建或调整了.gitattributes
,您应该执行一次性的行尾重新规范化。
请注意,GitHub Desktop 应用程序可以在您打开项目的 Git 存储库后建议并创建一个.gitattributes
文件。要尝试这个功能,请单击齿轮图标(位于右上角)> 存储库设置... > 行尾和属性。系统会要求您添加推荐的.gitattributes
,如果您同意,该应用程序还将对存储库中的所有文件进行规范化处理。
最后,Mind the End of Your Line这篇文章提供了更多背景知识,并解释了Git在相关问题上的发展。我认为这是必读的。
你可能有团队中使用EGit或JGit(像Eclipse和TeamCity这样的工具)提交其更改的用户。那么你就没有办法了,因为@gatinueta在此答案的评论中解释道:
如果你的团队中有人使用EGit或JGit工具,那么这个设置将无法完全满足你,因为这些工具会忽略.gitattributes并愉快地检入CRLF文件https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372
一个技巧可能是让他们在另一个客户端中提交更改,比如SourceTree。我们当时的团队喜欢这个工具,因为它适用于许多用例。
谁说软件容易呢? :-/
不要转换行尾符。这不是版本控制系统的工作,它只是存储和版本化数据。现代文本编辑器都可以读取两种类型的行尾符。
你几乎总是希望使用autocrlf=input
,除非你确切知道自己在做什么。
以下是一些额外的上下文:
如果你喜欢 DOS 结尾符,则应该设置为
core.autocrlf=true
,而如果你更喜欢 Unix 换行符,则应该设置为core.autocrlf=input
。在这两种情况下,你的Git存储库中只会有 LF,这是正确的方式。唯一不能设置为core.autocrlf=false
的场景是:自动启发式可能会错误地将某些二进制文件检测为文本,从而破坏您的文件,为此引入了一个名为core.safecrlf
的选项来警告用户发现不可逆转的更改。 实际上,存在两种不可逆转的更改可能性——混合换行符的文本文件,其中规范化很重要,因此可以忽略此警告,或者(非常不太可能)Git 错误地将您的二进制文件检测为文本。然后,您需要使用属性来告诉 Git 这个文件是二进制的。
上面的段落最初摘自 gmane.org 上的一个主题,但该网站已经关闭。
core.autocrlf=input
是标准答案。对于大多数用例,core.autocrlf=true
和core.autocrlf=false
过于热衷于处理换行符(当然是以相反但同样可怕的方式),因此本质上是具有破坏性的。"Git for Windows" 真的应该默认为“按原样提取,提交 Unix 风格的换行符”(即 core.autocrlf=input
)作为其换行策略。它没有。所以在这里,我们还在无休止地争论这个问题,竟然已经到了 2015 年。 - Cecil Curry在混合环境(Microsoft + Linux + Mac)中,有两种替代策略可以使行结束符保持一致:
find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
在Linux/UNIX上设置core.autocrlf
为input
,在MS Windows上设置为true
(可以设置为存储库级别或全局级别)
git config --global core.autocrlf input
可选地,将core.safecrlf
设置为true
(停止)或warn
(提示)可以添加额外的保护,比较反转换行符转换是否会导致相同的文件。
git config --global core.safecrlf true
将整个目录树中的换行符转换为同一格式
find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'
向您的代码库添加一个.gitattributes文件
echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'
不用担心二进制文件,Git应该能够很好地处理它们。
dos2unix
是一个命令行工具,根据你的系统可能需要额外安装。它的作用是将文本文件从 DOS 或 Windows 格式转换为 Unix 格式。 - lukmdodos2unix
时要非常小心 - 存在破坏.git/index
的风险,而且我们不需要将其应用于每个文件。最好使用类似于 find ./ -name "*.html"
这样的命令,并指定你想应用它的文件。 - cregoxfind
命令之前,请注意:Git for Windows 自带的 dos2unix
命令在无参数情况下具有特殊(在我看来是愚蠢和危险的)行为:它不会改变为 UNIX 的换行格式,而是切换换行格式(DOS <-> UNIX)。请注意。 - leonbloy考虑到 Windows 用户更喜欢在文本文件中使用 CRLF
,而 Linux/Mac 用户更喜欢使用 LF
,从一个仓库维护者的角度提供答案:
对我来说,最好的策略(解决问题较少)是:即使你正在开发一个仅限于 Windows 的项目,也要将所有文本文件保留为LF
格式,并且让客户自由选择他们喜欢的换行符风格,只要他们选择了一个 core.autocrlf
属性值,这个值将遵循你的策略(仓库中的 LF)在提交时暂存文件。
暂存是许多人在尝试理解换行策略时所困惑的内容。在选择正确的 core.autocrlf
属性值之前,理解以下几点至关重要:
.git/
子目录内的另一个位置复制该文件,并转换行尾(取决于客户端配置中的 core.autocrlf
值)。所有这些都是本地完成的。core.autocrlf
就像提供一个回答问题的答案(在所有操作系统上完全相同的问题):“Git 客户端应该:false:
"不要做任何事情",input:
"只做 b"true
: "同时做 a 和 b"幸运的是
core.autocrlf: true
,Linux/Mac:core.autocrlf: false
)与LF-only-repo策略兼容。不幸的是:
core.autocrlf
值core.autocrlf=false
并添加了一个带CRLF的文件以进行提交。为了尽快检测到由上述客户端提交的非lf文本文件,您可以按照---更新2---所述的操作进行(git grep -I --files-with-matches --perl-regexp '\r' HEAD
,在使用--with-libpcre
标志编译的客户端上)
这里有个问题:作为存储库维护者,我保持git.autocrlf=input
,这样我就可以通过再次添加提交来修复任何错误提交的文件。然后我提供一个提交文本:“修复错误提交的文件”。
就.gitattributes
而言,我不依赖它,因为有更多的ui客户端不理解它。我只使用它为文本和二进制文件提供提示,并可能标记一些应在任何地方保持相同行结尾的异常文件:
*.java text !eol # Don't do auto-detection. Treat as text (don't set any eol rule. use client's)
*.jpg -text # Don't do auto-detection. Treat as binary
*.sh text eol=lf # Don't do auto-detection. Treat as text. Checkout and add with eol=lf
*.bat text eol=crlf # Treat as text. Checkout and add with eol=crlf
答案: 为了避免在提交时出现单个字母更改,看起来像5000行更改,只是因为执行更改的客户端在添加之前将整个文件从crlf转换为lf(或反之亦然)。当涉及到冲突解决时,这可能会非常痛苦。或者在某些情况下,这可能是不合理冲突的原因。
Git客户端的默认设置在大多数情况下都有效。即使您只有Windows客户端、Linux客户端或两者都有。它们是:
core.autocrlf=true
表示在检出时将行转换为CRLF,并在添加文件时将行转换为LF。core.autocrlf=input
表示在检出时不要转换行(因为文件应该以LF提交),并在添加文件时将行转换为LF(如果需要)。
(-- 更新3 -- :似乎这默认为false
,但同样可以正常工作)该属性可以在不同的范围内设置。我建议在--global
范围内明确设置,以避免描述在最后的一些IDE问题。
git config core.autocrlf
git config --global core.autocrlf
git config --system core.autocrlf
git config --local core.autocrlf
git config --show-origin core.autocrlf
git config --global core.autocrlf false
(如果你只有Windows客户端),与git文档中所提出的相反。将其设置为false会在repo中提交带有CRLF的文件。但真的没有理由这样做。你永远不知道是否需要与linux用户共享项目。而且这是每个加入项目的客户机使用默认值之外的额外步骤。*.bat
*.sh
),您可以使用.gitattributes
来检查它们是否使用LF或CRLF进行检出。git grep -I --files-with-matches --perl-regexp '\r' HEAD
(注意:在Windows客户端上仅通过git-bash
工作,在Linux客户端上仅在使用--with-libpcre
编译时才能正常运行./configure
)。
- 如果通过执行上述命令找到任何此类文件,请将其更正。这涉及以下步骤(至少在Linux上):
- 设置core.autocrlf=input
(--- 更新3 ---)
- 更改文件
- 恢复更改(文件仍显示为已更改)
- 提交它
- 仅使用最少的.gitattributes
- 指示用户将core.autocrlf
描述为其默认值。
- 不要完全依赖于.gitattributes
的存在。 IDE的git客户端可能会忽略它们或以不同的方式处理它们。# Always checkout with LF
*.sh text eol=lf
# Always checkout with CRLF
*.bat text eol=crlf
-text
(例如*.zip
或*.jpg
文件):不会被视为文本。因此不会尝试进行换行符转换。通过转换程序可能还是有差异的。
- text !eol
(例如*.java
、*.html
文件):被视为文本,但没有设置EOL样式偏好。因此使用客户端设置。
- -text -diff -merge
(例如*.hugefile
文件):不被视为文本。没有差异/合并。git grep -I --files-with-matches --perl-regexp '\r' HEAD
我已经花了很多时间来找到最好的使用.gitattributes的方法,最终意识到我不能依赖它。不幸的是,只要存在基于JGit的编辑器(无法正确处理.gitattributes),安全的解决方案就是在编辑器层面上强制使用LF。Windows/Linux客户端: core.autocrlf=input
提交的.gitattributes
: * text=auto eol=lf
提交的.editorconfig
(http://editorconfig.org/) 是一种标准化的格式,结合编辑器插件使用:
.gitattributes
行,在 Git < 2.10 中会产生意想不到的后果,请参考 https://dev59.com/Tl0b5IYBdhLWcg3wO_I_#29508751。 - phkgit config --global core.autocrlf false
,并建议仅通过 .gitattributes
指令来处理行尾符。 - VonC使用core.autocrlf=false
可以防止我在Visual Studio 2010项目中签出文件时立即将所有文件标记为已更新。开发团队的其他两名成员也使用Windows系统,因此不涉及混合环境,但是与存储库一起提供的默认设置始终会在克隆后立即将所有文件标记为已更新。
我想关键是找到适合您环境的CRLF设置。特别是由于在我们Linux系统上的许多其他存储库中设置autocrlf=true
可以产生更好的结果。
20多年过去了,我们仍然在处理操作系统之间的行结尾差异...悲哀。
LF
作为行分隔符的HTTP库,尽管文本Internet协议必须使用CRLF
... - Luaan尝试将core.autocrlf
配置选项设置为true
。还要查看core.safecrlf
选项。
实际上,由于(重点在此):“如果对于core.autocrlf的当前设置不是这种情况,则git会拒绝文件”,因此听起来像你的存储库中已经设置了core.safecrlf
。
如果是这种情况,则您可能需要检查文本编辑器是否配置为一致使用换行符。如果文本文件包含混合的LF和CRLF行尾,那么您可能会遇到问题。
最后,我认为简单地“使用所给出的”在Windows上使用LF终止行将引起更多问题。 Git具有上述选项,以尝试以明智的方式处理行尾,因此使用它们是有意义的。
以下是供 Windows 和 Visual Studio 用户与 Mac 或者 Linux 用户共享代码的两种选择。详细解释请参考gitattributes手册。
在你的repo的.gitattributes
文件中添加如下内容:
* text=auto
LF
行结尾的文件得到规范化。根据你所用的操作系统(core.eol
设定),工作树中的文件会被规范化为Unix系统的LF
或Windows系统的CRLF
。这是Microsoft .NET仓库使用的配置。例如:Hello\r\nWorld
将始终在存储库中标准化为:
Hello\nWorld
在结账时,Windows中的工作树将被转换为:
Hello\r\nWorld
Hello\nWorld
git status
将显示这些文件已完全修改,这可能会给其他用户合并其更改带来麻烦。有关更多信息,请参见更改行尾之后刷新存储库。
如果在 .gitattributes
文件中未指定 text
,Git 将使用 core.autocrlf
配置变量来确定是否应转换该文件。
对于 Windows 用户,git config --global core.autocrlf true
是一个很好的选择,因为:
LF
行尾。如果存储库中存在未标准化的文件,则此设置将不会触及它们。CRLF
行尾。这种方法的问题是:
autocrlf = input
的 Windows 用户,则会看到一堆带有 LF
行尾的文件。对团队的其他成员没有危害,因为您的提交仍将使用 LF
行尾进行标准化。core.autocrlf = false
的 Windows 用户,则会看到一堆带有 LF
行尾的文件,并且您可能会将带有 CRLF
行尾的文件引入存储库中。autocrlf = input
,可能会从具有 core.autocrlf = false
的 Windows 用户那里获得带有 CRLF
文件行尾的文件。git config --global core.autocrlf true
,而不是 git config --global core.autocrl true
。 - JellicleCatAdd following lines to a config's [alias]
section. This command lists all changed (i.e. modified/new) files:
lc = "!f() { git status --porcelain \
| egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
| cut -c 4- ; }; f "
Convert all those changed files into dos format:
unix2dos $(git lc)
Optionally ...
Create a git hook for this action to automate this process
Use params and include it and modify the grep
function to match only particular filenames, e.g.:
... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
Feel free to make it even more convenient by using an additional shortcut:
c2dos = "!f() { unix2dos $(git lc) ; }; f "
... and fire the converted stuff by typing
git c2dos
core.autocrlf=false
——我喜欢在任何地方使用LF(换行符),但是一些Windows工具(例如Visual Studio)坚持在某些文件中使用CRLF(回车和换行符),甚至在某些文件中混合两种格式。不改变行结束符是最安全的选择。如果你知道自己在做什么,我可能会使用core.autocrlf=input
,并针对Windows上对行结束符敏感的项目进行特殊处理。正如其他人指出的那样,每个像样的文本编辑器现在都支持LF结束符。实际上,我认为core.autocrlf=true
可能会引起更多麻烦,而不是防范问题。 - Adrian*.sh text eol=lf
。这会将文本文件行尾的换行符规范化为 LF 格式,以确保在不同操作系统和编辑器之间的兼容性。 - Christophe Roussy