如何在Git中标准化工作树行结尾?


76

我已经克隆了行尾不一致的存储库。我添加了一个.gitattributes,它为我要标准化的文件设置了text属性。现在,当我提交更改时,我收到消息:

warning: CRLF will be replaced by LF in FILE.
The file will have its original line endings in your working directory.

如何让git为我规范化文件的工作副本?最好我想让git标准化整个工作树。


对于2019年遇到此问题的人,请注意,第二个答案(@philippn提供)现在比当前接受的答案更好
CharlieB

Answers:


90

使用Git客户端2.16和更高版本,现在有一种更简单的方法来执行此操作。只需使用:

git add --renormalize .

注意:最好使用干净的工作区进行此操作。有关详细信息,请参见:


1
我只是在Windows的Git Bash上尝试了此操作,它在存储库中暂存了每个文件以供提交。
william.berg

1
我有一条错误消息:error: unknown option 'renormalize'
Ryan Nghiem

@RyanNghiemgit --version说什么?我想它早于2.16,并且您需要升级。HTH
菲律宾,

2
@cja“清洁工作区”,如:命令git status返回类似内容nothing to commit, working tree clean
philippn

1
这对我根本什么都没有做。:-/
Timmmm '20年

101

对于使用v2.16或更高版本的用户,您可以简单地使用:

git add --renormalize .  # Update index with renormalized files
git status               # Show the files that will be normalized
git commit -m "Introduce end-of-line normalization"

这些方向直接来自gitattributes。对于较旧的版本,文档 (v2.12之前的版本)提供了不同的答案:

rm .git/index     # Remove the index to force git to
git reset         # re-scan the working directory
git status        # Show files that will be normalized
git add -u
git add .gitattributes
git commit -m "Introduce end-of-line normalization"

编辑完后,请执行以下步骤.gitattributes

更新资料

似乎有些用户在使用上述说明时遇到了麻烦。gitattributes(2.12至2.14)的更新文档显示了一组新的说明(在编辑.gitattributes文件之后):

git read-tree --empty   # Clean index, force re-scan of working directory
git add .
git status        # Show files that will be normalized
git commit -m "Introduce end-of-line normalization"

感谢@ vossad01指出这一点。

同样,无论使用哪种解决方案,工作副本中的文件仍保留其旧行结尾。如果要更新它们,请确保您的工作树是干净的并使用:

git rm --cached -r .
git reset --hard

现在,行尾在您的工作树中将是正确的。


这行得通,谢谢!我一直在浏览gitattributes文档,但要阅读的内容太多,所以我对它有所了解,找不到我想要的东西。我现在觉得很蠢。
user11171 2013年

不用担心,它发生了!它并不像应该找到的那么容易。:-)
John Szakmeister

11
.gitattributes首次添加或更改设置时,此方法有效,但如果工作树具有不同的EOL(至少对于MsysGit则没有),则该方法无效。为此,它似乎已工作git rm --cached -r .,然后git reset --hard工作了(警告:破坏了您的工作树)。来自help.github.com/articles/dealing-with-line-endings
waddlesplash 2014年

1
Git发生了什么改变从而打破了这一点?我已经使用了很多次,但是现在在一个无法正常工作的存储库中(git 2.13.0,linux)。相反,我必须git add .在删除索引后执行操作(注意工作目录中以前未跟踪的任何内容)。
vossad01

4
git read-tree --empty; git add .变体要谨慎。使用.gitignore时将忽略的所有跟踪文件都将被删除。该文档现在建议git add --renormalize .
vossad01

9

替代方法(仅在使用的命令中有所不同)

确保存储库中没有任何待处理的更改:

$ git status
$ git stash

修改,.gitattributes以便CRLF解释将更改:

$ echo "*.txt  text" >>.gitattributes
$ git commit -m "Made .txt files a subject to CRLF normalization." -- .gitattributes

从索引中删除数据并刷新工作目录:

$ git rm --cached -r .
$ git reset --hard

查看Git建议的CRLF修复程序:

$ git ls-files --eol
$ git status
$ git diff

同意Git的决定:

$ git add -u
$ git commit -m "Normalized CRLF for .txt files"

重新加载更改,就像完成干净克隆一样:

$ git rm --cached -r .
$ git reset --hard

1
注意:Git 2.8中新增了--eolto选项git ls-files(不再是新选项,但是有些人甚至在2018年底仍在使用Git 1.7!)
torek '18

4

.gitattributes设置只会影响新的提交。如果此存储库发布历史记录(没有其他历史记录依赖于此存储库),则您可能需要遍历整个历史记录。在Unix / Linux中,您可以结合使用dos2unix(1)来修复所有文件find(1),并使用历史记录重写filter-branch(请参见git书中的讨论)甚至可以清理项目的全部历史记录。

在新克隆上要格外小心。与可能有克隆的任何人联系,并建议他们您想做什么。


3
我通常会建议不要使用此解决方案,除非完美的历史很重要。通过重写历史,有很多方法可以使自己步履蹒跚。一次提交即可标准化存储库中的文件,然后让.gitattributes从此开始进行工作。
angularsen,2013年

@angularsen,如果重要的是发布干净的,可用的历史记录...这就是为什么我建议您使用干净的新克隆,并在对其进行过检查后(重新)发布它。
vonbrand

1

如果.gitattributes中的* text = auto选项使Git存储库中包含带有CRLF(Windows)行尾且现已标记为文本的文件(请参见https://marc.info/?l=git&m = 154484903528621&w = 2)。标准的renormalize选项不能与LFS过滤器一起正常使用,因此其他答案中的说明或例如https://help.github.com/en/articles/dealing-with-line-endings上的说明均无法正常工作。相反,这些步骤对我们有用:

情况:

  • 在Windows上
  • Git存储库包含CR和CRLF行尾的文件
  • 在.gitattributes中添加了* text = auto(因此不依赖于在Windows上设置了core.crlf = auto的用户)
  • 还将LFS跟踪文件的-crlf更改为-text,不确定是否需要。

    1. 从出现行尾问题的分支中创建一个新分支(假设那里没有未提交的更改):git checkout -b feature / doing-stuff-fix-eol
    2. 从.gitattributes中删除LFS过滤器(将所有'filter = lfs diff = lfs merge = lfs'替换为空)
    3. 提交并推送:git commit -a -m“为EOL修复禁用LFS筛选器”
    4. 移至非git资料夹
    5. 全局卸载LFS:git lfs卸载
    6. 创建一个新的存储库克隆:git clone -b feature / doing-stuff-fix-eol [远程存储库URL] fix-eol
    7. 规范行尾:git add --renormalize。(注意点将所有文件重新规范化)
    8. 仅检查正确的标准化文件。它不应包含通常由LFS处理的文件!
    9. 提交并推送(保存哈希):git commit -m“修复行尾”
    10. 移至非git资料夹
    11. 全局安装LFS:git lfs install
    12. 转到原始存储库克隆并拉出
    13. 签出原始分支:git checkout功能/ doing-stuff
    14. Cherry选择eol修复提交并推送:git cherry-pick [hash]
    15. 删除eol分支并推送
    16. 删除eol储存库克隆(如果需要修复更多分支,则保留该克隆)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.