我曾被Windows/Linux git的行结束问题所困扰。通过GitHub, MSysGit和其他来源,似乎最好的解决方案是让您的本地回购设置为使用linux风格的行结束符,但设置核心。专制是真实的。不幸的是,我没有做到这一点足够早,所以现在每次我拉改变线结束是borked。

我以为我在这里找到了答案,但我不能让它为我工作。我的Linux命令行知识有限,所以我甚至不确定“xargs fromdos”行在他的脚本中起什么作用。我不断收到关于不存在这样的文件或目录的消息,当我设法将其指向一个现有目录时,它告诉我我没有权限。

我已经在Windows和Mac OS X终端上尝试了MSysGit。


当前回答

gitattributes的git文档现在记录了另一种“修复”或规范化项目中所有行结束符的方法。以下是要点:

$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"

如果有任何文件不应该 正常显示在git状态, 之前不设置它们的文本属性 运行git add -u。 manual.pdf语境 相反,git所做的文本文件 未检测可有归一化 手动启用。 weirdchars.txt文本

这利用了2018年1月发布的git v2.16.0中添加的一个新的——renorize标志。 但如果你有“未分级删除的文件”,它可能会失败,因此先执行这些文件,比如:

git ls-files -z --deleted | xargs -0 git add

对于旧版本的git,有更多的步骤:

$ echo "* text=auto" >>.gitattributes
$ 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"

其他回答

git status --short|grep "^ *M"|awk '{print $2}'|xargs fromdos

解释:

Git状态——短 这将显示git知道和不知道的每一行。不在git控制下的文件在行首用'?'标记。被修改的文件用M标记。 grep "^ *M" 这只会过滤掉那些被修改过的文件。 Awk '{打印$2}' 这只显示没有任何标记的文件名。 xargs fromdos 这将从前面的命令中获取文件名,并通过实用程序'fromdos'运行它们来转换行结束符。

我处理行尾的程序如下(在多次回购中进行了战斗测试):

当创建一个新的repo时:

将.gitignore和README.md等典型文件放在第一次提交时。gitignore

在处理现有的回购时:

Create / modify .gitattributes accordingly git commit -a -m "Modified gitattributes" git rm --cached -r . && git reset --hard && git commit -a -m 'Normalize CRLF' -n" -n (--no-verify is to skip pre-commit hooks) I have to do it often enough that I defined it as an alias alias fixCRLF="..." repeat the previous command yep, it's voodoo, but generally I have to run the command twice, first time it normalizes some files, second time even more files. Generally it's probably best to repeat until no new commit is created :) go back-and-forth between the old (just before normalization) and new branch a few times. After switching the branch, sometimes git will find even more files that need to be renormalized!

在.gitattributes中,我显式地声明所有文本文件具有LF EOL,因为通常Windows工具与LF兼容,而非Windows工具与CRLF不兼容(甚至许多nodejs命令行工具都假设LF,因此可以更改文件中的EOL)。

.gitattributes的内容

我的.gitattributes通常是这样的:

*.html eol=lf
*.js   eol=lf
*.json eol=lf
*.less eol=lf
*.md   eol=lf
*.svg  eol=lf
*.xml  eol=lf

要了解git在当前回购中跟踪哪些不同的扩展,请查看这里

正常化后的问题

一旦完成,还有一个更常见的警告。

假设您的master已经是最新的和规范化的,然后签出过时的分支。通常在签出分支之后,git会将许多文件标记为已修改。

解决方案是做一个假提交(git add -A。&& git commit -m 'fake commit'),然后git rebase master。在rebase之后,假提交应该会消失。

gitattributes的git文档现在记录了另一种“修复”或规范化项目中所有行结束符的方法。以下是要点:

$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"

如果有任何文件不应该 正常显示在git状态, 之前不设置它们的文本属性 运行git add -u。 manual.pdf语境 相反,git所做的文本文件 未检测可有归一化 手动启用。 weirdchars.txt文本

这利用了2018年1月发布的git v2.16.0中添加的一个新的——renorize标志。 但如果你有“未分级删除的文件”,它可能会失败,因此先执行这些文件,比如:

git ls-files -z --deleted | xargs -0 git add

对于旧版本的git,有更多的步骤:

$ echo "* text=auto" >>.gitattributes
$ 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"

修复这个问题最简单的方法是提交一次,修复所有的行结束符。假设您没有任何修改过的文件,那么您可以按照下面的方法进行操作。

# From the root of your repository remove everything from the index
git rm --cached -r .

# Change the autocrlf setting of the repository (you may want 
#  to use true on windows):
git config core.autocrlf input

# Re-add all the deleted files to the index
# (You should get lots of messages like:
#   warning: CRLF will be replaced by LF in <file>.)
git diff --cached --name-only -z | xargs -0 git add

# Commit
git commit -m "Fixed crlf issue"

# If you're doing this on a Unix/Mac OSX clone then optionally remove
# the working tree and re-check everything out with the correct line endings.
git ls-files -z | xargs -0 rm
git checkout .

以下是我如何使用git filter-branch在整个历史中固定所有的行结尾。^M字符需要使用CTRL-V + CTRL-M输入。我使用dos2unix来转换文件,因为这会自动跳过二进制文件。

$ git filter-branch --tree-filter 'grep -IUrl "^M" | xargs -I {} dos2unix "{}"'