如何在 Git 中规范化工作树行结尾?

我克隆了一个行结尾不一致的存储库。我已经添加了一个 .gitattributes,它为我想要规范化的文件设置文本属性。现在,当我提交更改时,我得到的信息是:

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

我怎样才能使 git 正常化我的文件的工作副本为我?我希望 git 能够规范化整个工作树。

57127 次浏览

The .gitattributes settings will only affect new commits. If this repository has no history published (no others depending on it), you might want to go through the whole history. In Unix/Linux, you can use dos2unix(1) to fix all files in combination with find(1), and using the history rewriting of filter-branch (see the discussion in the git book) you can even clean up the full history of the project.

Use with utmost care, on a fresh clone. Get in contact with anybody who might have a clone, and advise them what you want to do.

For those using v2.16 or better, you can simply use:

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"

These directions are straight out of the gitattributes. For older versions, the docs (prior to v2.12) provide a different answer:

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"

Do this sequence after you have edited .gitattributes.

Update

It appears some users have had trouble with the above instructions. Updated docs for gitattributes (2.12 to 2.14) shows a new set of instructions (after editing the .gitattributes files):

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"

Thanks to @vossad01 for pointing this out.

Also, with either solution the files in your working copy still retain their old line endings. If you want to update them, make sure your working tree is clean and use:

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

Now the line endings will be correct in your working tree.

Alternative approach (differs only in command used)

Make sure you have no any pending changes in repository:

$ git status
$ git stash

Modify .gitattributes so CRLF interpretation will changed:

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

Remove data from index and refresh working directory:

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

Review CRLF fixes that Git proposes:

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

Agree with Git decision:

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

Reload changes as if clean clone was done:

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

With Git client 2.16 and higher there is now a much simpler way to do this. Just use:

git add --renormalize .

Note: it's better to do this with a clean workspace. For details, see:

The * text=auto option in .gitattributes leaves the Git repository in an 'illegal state' if it contains files with CRLF (Windows) line endings which are now marked as text (see https://marc.info/?l=git&m=154484903528621&w=2). The standard renormalize option does not work correctly with the LFS filters, so the instructions in the other answers or for example at https://help.github.com/en/articles/dealing-with-line-endings, do not work correctly. Instead these steps worked for us:

Situation:

  • On Windows
  • Git repository contained files with both CR and CRLF line endings
  • Added * text=auto to .gitattributes (so not depended on user having set core.crlf=auto on Windows)
  • Also changed the -crlf to -text for LFS tracked files, not sure that is needed.

    1. Create a new branch from the branch with the line ending problem (assuming no uncommitted changes there): git checkout -b feature/doing-stuff-fix-eol
    2. Remove the LFS filters from .gitattributes (replace all 'filter=lfs diff=lfs merge=lfs ' with nothing)
    3. Commit and push: git commit -a -m "Disable LFS filters for EOL fix"
    4. Move to non-git folder
    5. Uninstall LFS globally: git lfs uninstall
    6. Create a new repository clone: git clone -b feature/doing-stuff-fix-eol [remote repository url] fix-eol
    7. Normalize the line endings: git add --renormalize . (note the dot to renormalize all files)
    8. Check only the correct files normalized. It should not include files normally handled by LFS!
    9. Commit and push (save the hash): git commit -m "Fix line endings"
    10. Move to non-git folder
    11. Install LFS globally: git lfs install
    12. Go to original repository clone and pull
    13. Checkout your original branch: git checkout feature/doing-stuff
    14. Cherry pick the eol fix commit and push: git cherry-pick [hash]
    15. Delete the eol branch and push
    16. Delete the eol repository clone (or keep around if you need to fix more branches)

The merge.renormalize configuration setting may be useful.

I had to re-clone repo with this flag -c core.autocrlf=false, and it worked, no other config required.

Like this:

git clone -c core.autocrlf=false https://github.com/any-repo.git

Our project initially was made with LF on Mac, but on Windows it was automatically converted to CRLF. We use eslint and it underlined every line of code, until I re-cloned it.