2017-10-11 61 views
1

我有一个存储库,其中包含5个使用CRLF提交的文件。我不知道这是怎么发生的,但在干净的检出,如果我用这个命令将打印5个文件(出几百):在git上如何使用CRLF提交文件?

git grep -I --files-with-matches --perl-regexp '\r' HEAD

有谁知道我可以重现这个问题?换句话说,什么是可能导致这种情况的一组git设置?

回答

2

在内部,Git只是存储原始数据。如果您运行git hash-object -w,则可以将任何您喜欢的blob数据推送到存储库(尽管您需要附加标签或将该blob添加到索引以将其存储到新的提交中)。

正如我在回答What does "check out code" mean in git documentation for line endings?时指出的那样,Git将在启用此类翻译的任何文件上应用CRLF到LF唯一的行尾翻译,在您运行该文件的git add时。结果是索引中的文件版本(或者更确切地说,索引中的blob散列表示in-repo blob对象)具有仅LF的行结尾。

如果您在使用该文件运行git add:全局禁用

  • 翻译,或
  • 翻译在那个特定的路径名​​称禁用

然后Git的不会做那些翻译,并且文件的索引版本将具有其在工作树版本中具有的任何'\r'字符。

.gitattributes和/或core.autocrlf中的设置控制是否启用翻译,如果是,则执行哪些翻译。由于历史设置(从Git什么也没做,到加入Windows支持的早期阶段,通过Git的各种中间版本,到当前相当复杂的.gitattributes方法),所有这些规则都非常复杂。

换句话说什么是可以导致这种情况的一组git设置?

有许多不同的方式来做到这一点,但是这是目前为止最简单的一个是写一个.gitattributes文件只有:

* -text 

或设置core.autocrlffalse(但要注意.gitattributes一般覆盖core.autocrlf)。现在,Git会将所有文件视为二进制文件,在git add期间不进行“清理”,在git checkout期间没有“打印”。除了您自己创建的任何更改,或者通过运行程序生成工作树文件以外,工作树内容现在都将匹配索引内容字节逐字节。然后您可以将这些新文件git add添加到索引,并将它们以字节逐字节的方式复制;你所做的每个新的git commit都将使用索引中的内容。

一旦存储,作为永久的和不可改变的提交,你关心的特定文件的特定版本,你可以修改.gitattributes包含任何其他设置你想测试,并运行git checkout <commit> -- <path>,使GIT中的文件复制从提交,索引,通过模糊过滤器,并进入工作树。您可以任意修改任何工作树文件,然后运行git add <path>以通过清理过滤器运行该文件,以将其复制到索引中。这些过滤器将由您在运行命令时.gitattributes中的任何内容来控制,因此您可以尝试不同的属性而无需进行新的提交。

+0

如果'core.autocrlf' = true(windows)/'core.autocrlf = input'(linux),上面的结论是否可以(使用标准的git客户端)执行包含CRLF的提交? ),并且没有.gitattributes存在? –

+0

@MarinosAn:不,因为如果您从某个文件中的CRLF结尾提交开始,并将该文件从提交中提取到索引中,则该文件的索引版本具有CRLF结尾。如果您从未将该文件“git add”添加到索引中,则索引版本继续具有CRLF结尾,并且下一次提交使用索引版本。此时*没有设置很重要:*下一个提交的内容与前一个提交的内容相同。 – torek

+0

你的答案真的清除了很多东西。还帮助我了解一些文件在git中如何变得如此持久不可变:https://stackoverflow.com/a/45030792/1555615 –

0

你可能会使用git config --global core.autocrlf true

为了更好的解释看docs

相关问题