2017-10-11 44 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