我有一个存储库,其中包含5个使用CRLF提交的文件。我不知道这是怎么发生的,但在干净的检出,如果我用这个命令将打印5个文件(出几百):在git上如何使用CRLF提交文件?
git grep -I --files-with-matches --perl-regexp '\r' HEAD
有谁知道我可以重现这个问题?换句话说,什么是可能导致这种情况的一组git设置?
我有一个存储库,其中包含5个使用CRLF提交的文件。我不知道这是怎么发生的,但在干净的检出,如果我用这个命令将打印5个文件(出几百):在git上如何使用CRLF提交文件?
git grep -I --files-with-matches --perl-regexp '\r' HEAD
有谁知道我可以重现这个问题?换句话说,什么是可能导致这种情况的一组git设置?
在内部,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.autocrlf
到false
(但要注意.gitattributes
一般覆盖core.autocrlf
)。现在,Git会将所有文件视为二进制文件,在git add
期间不进行“清理”,在git checkout
期间没有“打印”。除了您自己创建的任何更改,或者通过运行程序生成工作树文件以外,工作树内容现在都将匹配索引内容字节逐字节。然后您可以将这些新文件git add
添加到索引,并将它们以字节逐字节的方式复制;你所做的每个新的git commit
都将使用索引中的内容。
一旦存储,作为永久的和不可改变的提交,你关心的特定文件的特定版本,你可以修改.gitattributes
包含任何其他设置你想测试,并运行git checkout <commit> -- <path>
,使GIT中的文件复制从提交,索引,通过模糊过滤器,并进入工作树。您可以任意修改任何工作树文件,然后运行git add <path>
以通过清理过滤器运行该文件,以将其复制到索引中。这些过滤器将由您在运行命令时.gitattributes
中的任何内容来控制,因此您可以尝试不同的属性而无需进行新的提交。
你可能会使用git config --global core.autocrlf true
为了更好的解释看docs。
如果'core.autocrlf' = true(windows)/'core.autocrlf = input'(linux),上面的结论是否可以(使用标准的git客户端)执行包含CRLF的提交? ),并且没有.gitattributes存在? –
@MarinosAn:不,因为如果您从某个文件中的CRLF结尾提交开始,并将该文件从提交中提取到索引中,则该文件的索引版本具有CRLF结尾。如果您从未将该文件“git add”添加到索引中,则索引版本继续具有CRLF结尾,并且下一次提交使用索引版本。此时*没有设置很重要:*下一个提交的内容与前一个提交的内容相同。 – torek
你的答案真的清除了很多东西。还帮助我了解一些文件在git中如何变得如此持久不可变:https://stackoverflow.com/a/45030792/1555615 –