我尝试使用以crlf结尾的行提交文件,但失败了。

我花了一整天的时间在我的Windows电脑上尝试不同的策略,几乎要停止尝试使用Git,而是尝试使用Mercurial。

如何正确处理CRLF行结束符?


当前回答

——UPDATE 3——(与UPDATE 2不冲突)

考虑到windows用户更喜欢在CRLF上工作,而linux/mac用户更喜欢在文本文件上使用LF。从存储库维护者的角度提供答案:

对我来说,最好的策略(要解决的问题较少)是:将所有文本文件与LF保存在git repo中,即使你正在开发一个仅支持windows的项目。然后让客户自由选择他们喜欢的行结束风格,前提是他们选择了一个核心。在为提交暂存文件时,该属性值将尊重您的策略(回购上的LF)。

分期是许多人在试图理解换行策略如何工作时所困惑的。在为core选择正确的值之前,有必要了解以下几点。autocrlf属性:

Adding a text file for commit (staging it) is like copying the file to another place inside .git/ sub-directory with converted line-endings (depending on core.autocrlf value on your client config). All this is done locally. setting core.autocrlf is like providing an answer to the question (exact same question on all OS): "Should git-client: a. convert LF-to-CRLF when checking-out (pulling) the repo changes from the remote? b. convert CRLF-to-LF when adding a file for commit?" and the possible answers (values) are: false: "do none of the above", input: "do only b" true: "do a and and b" note that there is NO "do only a"

幸运的是

Git客户端默认值(windows: core。linux/mac: 核心。selflf: false)将与LF-only-repo策略兼容。 含义:windows客户端在签出存储库时默认转换为CRLF,在添加提交时转换为LF。linux客户端默认情况下不进行任何转换。这理论上保持你的回购只有lf。

不幸的是:

可能有GUI客户端不尊重git核心。autocrlf价值 可能有些人不使用一个值来尊重你的lf-回购策略。例如,他们使用核心。selflf =false并添加一个带有CRLF的文件用于提交。

要检测上述客户端提交的ASAP非lf文本文件,您可以遵循——update 2——(git grep -I——files-with-matches——perl-regexp '\r' HEAD,在使用:with-libpcre标志编译的客户端上)

这里有个问题:。我作为一个回购维护者保持一个git。selflf =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(或相反)。当涉及到冲突解决时,这可能是相当痛苦的。或者在某些情况下,它可能是不合理冲突的原因。


——更新2——

git客户端的错误在大多数情况下都可以工作。即使你只有windows客户端,linux客户端或者两者都有。这些都是:

windows:核心。selflf =true表示在签出时将行转换为CRLF,在添加文件时将行转换为LF。 linux:核心。selflf =input意味着在签出时不转换行(不需要,因为文件预计将使用LF提交),并在添加文件时将行转换为LF(如果需要)。 (——update3——:默认情况下这似乎是假的,但这也是好的)

该属性可以在不同的作用域中设置。我建议显式地在——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

此外,我强烈反对在windows上使用git配置全局核心。与git文档中建议的内容相反,自专制错误(如果你只有Windows客户端)。设置为false将在repo中使用CRLF提交文件。但真的没有理由。您永远不知道是否需要与linux用户共享项目。另外,对于每个加入项目的客户端来说,这是一个额外的步骤,而不是使用默认值。

现在对于一些特殊情况的文件(例如*.bat *.sh),你想用LF或CRLF签出它们,你可以使用.gitattributes

对我来说,最好的做法是:

Make sure that every non-binary file is committed with LF on git repo (default behaviour). Use this command to make sure that no files are committed with CRLF: git grep -I --files-with-matches --perl-regexp '\r' HEAD (Note: on windows clients works only through git-bash and on linux clients only if compiled using --with-libpcre in ./configure). If you find any such files by executing the above command, correct them. This in involves (at least on linux): set core.autocrlf=input (--- update 3 --) change the file revert the change(file is still shown as changed) commit it Use only the bare minimum .gitattributes Instruct the users to set the core.autocrlf described above to its default values. Do not count 100% on the presence of .gitattributes. git-clients of IDEs may ignore them or treat them differrently.

如前所述,一些东西可以添加到git属性中:

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf

我认为.gitattributes的其他安全选项,而不是对二进制文件使用自动检测:

-text(例如*.zip或*.jpg文件:不会被视为文本。因此不会尝试行结束转换。Diff可能通过转换程序实现) eol(例如,对于*.java,*.html:作为文本处理,但未设置eol样式首选项。所以使用客户端设置。) -text -diff -merge(例如*.)hugefile:不作为文本处理。没有差异/合并可能)

——之前的更新——

一个令人痛苦的客户端错误提交文件的例子:

netbeans 8.2(在windows上)会错误地使用crlf提交所有文本文件,除非你显式地设置了core。专制作为全球。这与标准的git客户端行为相矛盾,并在稍后更新/合并时导致许多问题。这就是为什么即使在还原时,某些文件也会显得不同(尽管它们并不是)。 即使您在项目中添加了正确的.gitattributes,在netbeans中也会发生相同的行为。

在提交后使用以下命令,至少可以帮助您及早检测git回购是否存在行结束问题

我花了几个小时来想出.gitattributes的最佳使用方法,最终意识到我不能指望它。 不幸的是,只要存在基于jgit的编辑器(它不能正确地处理.gitattributes),安全的解决方案就是在所有地方强制使用LF,即使是在编辑器级别。

使用以下抗crlf消毒剂。

Windows /linux客户端:core. selflf =input 提交。gitattributes: * text=auto eol=lf 提交的。editorconfig (http://editorconfig.org/),这是一种标准化的格式,结合编辑器插件: https://github.com/editorconfig/ https://github.com/welovecoding/editorconfig-netbeans/

其他回答

不要转换行结束符。VCS的工作不是解释数据——只是存储和版本它。每个现代文本编辑器都可以读取这两种行尾。

这是Windows和Visual Studio用户与Mac或Linux用户共享代码的两个选项。要了解更详细的解释,请阅读gitattributes手册。

* text = auto

在你的repo .gitattributes文件中添加:

*   text=auto

这将正常化所有的文件与LF行结束在回购。

取决于您的操作系统(核心。eol设置),工作树中的文件将被标准化为基于Unix系统的LF或基于Windows系统的CRLF。

这是Microsoft . net回购所使用的配置。

例子:

Hello\r\nWorld

将在回购中始终归一化为:

Hello\nWorld

签出时,Windows中的工作树将被转换为:

Hello\r\nWorld

签出时,Mac中的工作树将保留为:

Hello\nWorld

注意:如果您的repo已经包含了未规范化的文件,那么当您下次对这些文件进行任何更改时,git状态将显示这些文件已完全修改,这可能会让其他用户稍后合并他们的更改。有关详细信息,请参见更改行结束符后刷新存储库。

核心。独裁者= true

如果文本在. Git attributes文件中未指定,Git使用核心。selflf配置变量,以确定是否应该转换文件。

对于Windows用户,git配置——global core。专制是一个很好的选择,因为:

文件只有在添加到repo时才被归一化为LF行结束符。如果在repo中有未规范化的文件,此设置将不会触及它们。 所有文本文件都转换为工作目录中的CRLF行结束符。

这种方法的问题在于:

If you are a Windows user with autocrlf = input, you will see a bunch of files with LF line endings. Not a hazard for the rest of the team, because your commits will still be normalized with LF line endings. If you are a Windows user with core.autocrlf = false, you will see a bunch of files with LF line endings and you may introduce files with CRLF line endings into the repo. Most Mac users use autocrlf = input and may get files with CRLF file endings, probably from Windows users with core.autocrlf = false.

试着设定核心。自专制配置选项为true。还要看看核心。safecrlf选项。

实际上它听起来像核心。Safecrlf可能已经在你的存储库中设置了,因为(强调我的):

如果这不是当前设置的核心的情况。专制者,git将拒绝文件。

如果是这种情况,那么您可能需要检查您的文本编辑器是否配置为一致地使用行结束符。如果文本文件混合包含LF和CRLF行结束符,您可能会遇到问题。

最后,我觉得在Windows上简单地“使用您所给予的”和使用LF终止行的建议会导致比它解决的问题更多的问题。Git有上述选项来尝试以合理的方式处理行结束符,因此使用它们是有意义的。

使用核心。当我在Visual Studio 2010项目中检出文件时,selflf =false会阻止所有文件被标记为更新。开发团队的另外两名成员也使用Windows系统,因此混合环境没有发挥作用,但存储库附带的默认设置总是将所有文件标记为克隆后立即更新。

我认为最重要的是找到适合您的环境的CRLF设置。特别是在我们的Linux盒子上的许多其他存储库中,设置selff = true会产生更好的结果。

20多年后,我们仍然在处理操作系统之间的行尾差异……伤心。

在提出这个问题近四年后,我终于 找到了一个让我完全满意的答案!

详见github:帮助指南 处理行结束。

的行结束属性 对象中的文本属性直接回购 .gitattributes文件。该文件被提交 回购和覆盖核心。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,就应该执行一劳永逸的行尾重新规范化。

请注意,在应用程序中打开项目的Git repo后,GitHub桌面应用程序可以建议并创建一个.gitattributes文件。要尝试这一点,请单击齿轮图标(在右上角)> Repository settings…>行结束符和属性。你会被要求添加推荐的.gitattributes,如果你同意,应用程序也会对存储库中的所有文件进行规范化。

最后一篇文章是《注意你的底线》 提供了更多的背景知识,并解释了Git是如何发展的 手头的事情。我认为这是必读的。

您的团队中可能有使用EGit或JGit (Eclipse和TeamCity等工具使用它们)提交更改的用户。那么你就不走运了,就像@gatinueta在回答的评论中解释的那样:

如果您的团队中有人使用Egit或JGit,则此设置将不能完全满足您的要求,因为这些工具将忽略.git属性并愉快地检入CRLF文件https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372

一个技巧可能是让他们在另一个客户端提交他们的更改,比如SourceTree。在许多用例中,我们的团队更喜欢这个工具而不是Eclipse的EGit。

谁说软件很简单?: - /