Git最好的CRLF(回车,换行)处理策略是什么?
我试着用CRLF结束行提交文件,但是失败了。
我花了整整一天的时间在我的Windows计算机上尝试不同的策略,几乎被停止尝试使用Git,而是尝试使用Mercurial 。
每个答案只能分享一个最佳做法。
问了这个问题差不多四年了,我终于找到了一个完全满足我的答案 !
请参阅github中的详细信息:帮助 处理行结尾的指南。
Git允许您使用
.gitattributes
文件中的text属性直接设置repo的行结束属性。 这个文件被提交到repo中,并覆盖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
,你应该执行一遍又一遍的行结束重新规范化 。
请注意,在应用程序中打开项目的Git .gitattributes
后, GitHub桌面应用程序可以建议并创建一个.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 。 我们的团队当时喜欢使用Eclipse的EGit来处理许多用例。
谁说软件容易? : – /
不要转换行结尾。 解读数据不是VCS的工作 – 只是存储和版本。 无论如何,每个现代的文本编辑器都可以读取两种行结尾。
除非你真的知道你在做什么,你几乎总是需要autocrlf=input
。
以下是一些额外的内容
它应该是
core.autocrlf=true
如果你喜欢DOS结局或core.autocrlf=input
如果你喜欢unix新行。 在这两种情况下,你的Git仓库将只有LF,这是正确的事情。core.autocrlf=false
的唯一参数是自动启发式可能会错误地将某些二进制文件检测为文本,然后您的core.autocrlf=false
贴将被损坏。 因此,引入了core.safecrlf
选项来警告用户是否发生了不可逆转的变化。 事实上,有两种不可逆转的可能性 – 在文本文件中混合行结束,在这种规范化是可取的,所以这个警告可以忽略,或者(非常不可能)Git错误地检测到你的二进制文件为文本。 然后你需要使用属性来告诉Git这个文件是二进制的。
上面的这段话最初是从gmane.org上的一个帖子中拉出来的,但是之后它已经下降了。
在混合环境(Microsoft + Linux + Mac)中保持一致的两种替代策略:
A.全球所有存储库设置
1) 全部转换为一种格式
find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion'
2)将core.autocrlf
设置为在Linux / UNIX上input
,或者在MS Windowns(存储库或全局)上设置为true
。
git config --global core.autocrlf input
3)[可选]将core.safecrlf
设置为true
(停止)或warn
(唱歌:)以增加额外的防范,比较反转的换行符是否会导致相同的文件
git config --global core.safecrlf true
B.或者每个存储库设置
1) 全部转换为一种格式
find . -type f -not -path "./.git/*" -exec dos2unix {} \; git commit -a -m 'dos2unix conversion'
2)将.gitattributes
文件添加到您的存储库
echo "* text=auto" > .gitattributes git add .gitattributes git commit -m 'adding .gitattributes for unified line-ending'
不要担心你的二进制文件 – Git应该足够聪明。
更多关于safecrlf / autocrlf变量
尝试将core.autocrlf
配置选项设置为true
。 也看看core.safecrlf
选项。
其实这听起来像core.safecrlf
可能已经在您的存储库中设置,因为(重点是我的):
如果core.autocrlf的当前设置不是这种情况,那么git会拒绝这个文件 。
如果是这种情况,那么您可能需要检查文本编辑器是否配置为始终使用行尾。 如果文本文件包含LF和CRLF行结尾的混合,则可能会遇到问题。
最后,我觉得这个建议只是“使用你给的东西”,在Windows上使用LF终止的行会导致更多的问题,而不是解决的问题。 Git有上面的选项来尝试以合理的方式处理行尾,所以使用它们是有意义的。
使用core.autocrlf=false
停止所有的文件被标记为更新,只要我在我的Visual Studio 2010项目中签出。 开发团队的另外两名成员也使用Windows系统,因此混合环境无法发挥作用,但存储库随附的默认设置始终将所有文件都标记为在克隆后立即更新。
我想底线是要找到什么CRLF设置适用于您的环境。 特别是因为在我们Linux机器上的许多其他仓库中, autocrlf = true
会产生更好的结果。
20多年后,我们仍然在处理操作系统之间的差异……悲伤。
对于Windows和Visual Studio用户来说,这两个选项是与Mac或Linux用户共享代码的。 有关扩展解释,请阅读gitattributes手册 。
* text = auto
在您的repo的.gitattributes
文件中添加:
* text=auto
这将正常化所有的文件与LF
行结束回购。
根据您的操作系统( core.eol
设置),工作树中的文件将被标准化为基于Unix的系统的LF
或Windows系统的CRLF
。
这是Microsoft .NET回购使用的配置。
例:
Hello\r\nWorld
在回购总是会正常化为:
Hello\nWorld
在结帐时,Windows中的工作树将被转换为:
Hello\r\nWorld
结帐时,Mac中的工作树将保留为:
Hello\nWorld
注意:如果你的repo已经包含未被标准化的文件,
git status
会在下一次你做任何改变的时候显示这些文件被完全修改,其他用户以后可能会很难合并它们的改变。 更改行结束符后,请参阅刷新存储库以获取更多信息。
core.autocrlf = true
如果text
未在.gitattributes
文件中指定,Git将使用core.autocrlf
配置变量来确定文件是否应该被转换。
对于Windows用户, git config --global core.autocrlf true
是一个不错的选择,因为:
- 只有在添加到回购库时,文件才会标准化为
LF
换行符。 如果回购库中没有归档的文件,该设置将不会触及它们。 - 所有文本文件都转换为工作目录中的
CRLF
行尾。
这种方法的问题是:
- 如果你是一个
autocrlf = input
的Windows用户,你会看到一堆LF
行尾的文件。 对于其他队伍来说不是一个危险因素,因为你的犯下的命令仍然会用LF
结尾进行标准化。 - 如果你是一个
core.autocrlf = false
的Windows用户,你将会看到一堆带有LF
行结尾的文件,你可以把带有CRLF
行结尾的文件引入到repo中。 - 大多数Mac用户使用
autocrlf = input
,可能会从具有core.autocrlf = false
Windows用户获取带有CRLF
文件结尾的文件。
这只是一个解决方法:
在正常情况下,使用git附带的解决方案。 在大多数情况下这些工作很好。 如果您通过设置.gitattributes共享Windows和Unix系统上的开发,则强制为LF。
在我的情况下,有> 10个程序员在Windows中开发一个项目。 这个项目被CRLF检入, 没有选项强制LF。
一些设置在我的机器上内部写入,对LF格式没有任何影响; 从而在每次小文件更改时将一些文件全局更改为LF。
我的解决方案
Windows机器:让所有事情都是这样。 不要在意,因为你是一个默认的Windows“孤独的狼”开发者,你必须这样处理:“在世界上没有其他系统,是吗?
Unix的机
-
将以下行添加到配置的
[alias]
部分。 这个命令列出所有更改(即修改/新建)的文件:lc = "!f() { git status --porcelain \ | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \ | cut -c 4- ; }; f "
-
将所有这些更改的文件转换为dos格式:
unix2dos $(git lc)
-
可选…
-
为此操作创建一个git 钩子来自动化这个过程
-
使用params并包含它,并修改
grep
函数以仅匹配特定的文件名,例如:... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
-
通过使用额外的快捷方式,可以使其更加方便:
c2dos = "!f() { unix2dos $(git lc) ; }; f "
…通过打字来发射转换后的东西
git c2dos
-
我花了几个小时来想出最好的.gitattributes
使用,终于意识到,我不能指望它。
不幸的是,只要存在基于JGit的编辑器(不能正确处理.gitattributes
),安全的解决方案就是在编辑器级强制LF。
使用以下anti-CRLF
消毒剂。
-
windows / linux客户端:
core.autocrlf=input
-
提交的
.gitattributes
:* text=auto eol=lf
-
提交
.editorconfig
( http://editorconfig.org/ )这是一种标准化的格式,结合编辑插件:
—更新—
即使你不想使用上面的策略, 下面的命令就是你的朋友 ( 注意:在windows客户端上只能通过git-bash
和linux客户端才能在./configure
使用--with-libpcre
编译)。
# Print all files that have been committed with CRLF (more correctly that contain CR), so that you normalize them. git grep -I --files-with-matches --perl-regexp '\r' HEAD
一个痛苦的例子 :
netbeans 8.2 (在windows上)会错误地提交所有带回购CRLF的文本文件, 除非你明确地将core.autocrlf
设置为全局 。 这与标准的git客户端行为相矛盾,在更新/合并时会导致很多问题。 这是什么让一些文件看起来不同 (尽管不是), 即使你恢复 。
即使您已经将正确的.gitattributes
添加到您的项目中,netbeans中也会发生相同的行为。
在提交后使用上述命令,至少可以帮助您及早发现git仓库是否存在行结束问题。