280

我被 git 的 Windows/Linux 行尾问题所困扰。看来,通过 GitHub、MSysGit 和其他来源,最好的解决方案是将本地存储库设置为使用 linux 样式的行尾,但设置core.autocrlftrue. 不幸的是,我没有足够早地这样做,所以现在每次我拉变化时,行尾都是无聊的。

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

我已经在 Windows 上使用 MSysGit 和通过 Mac OS X 终端尝试过这个。

4

8 回答 8

400

解决此问题的最简单方法是进行一次修复所有行结尾的提交。假设您没有任何修改过的文件,那么您可以按如下方式执行此操作。

# 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 .
于 2009-10-02T19:03:20.847 回答
197

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 status 中,请在运行 git add -u 之前取消设置其文本属性。

manual.pdf -text

相反,git 没有检测到的文本文件可以手动启用规范化。

weirdchars.txt text

这利用了--renormalize2018 年 1 月发布的 git v2.16.0 中添加的新标志。对于旧版本的 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"
于 2011-01-13T18:32:28.353 回答
12

我处理行尾的程序如下(在许多 repos 上测试过):

创建新仓库时:

  • .gitattributes第一个提交与其他典型文件一起 .gitignore放入README.md

处理现有回购时:

  • .gitattributes相应地创建/修改
  • git commit -a -m "Modified gitattributes"
  • git rm --cached -r . && git reset --hard && git commit -a -m 'Normalize CRLF' -n"
    • -n--no-verify是跳过预提交钩子)
    • 我必须经常这样做,以至于我将其定义为别名alias fixCRLF="..."
  • 重复上一条命令
    • 是的,它是伏都教,但通常我必须运行该命令两次,第一次它规范化一些文件,第二次甚至更多文件。通常最好重复直到没有创建新的提交:)
  • 在旧分支(就在规范化之前)和新分支之间来回切换几次。切换分支后,有时候git会发现更多的文件需要重新规范化!

.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 在当前 repo 中跟踪了哪些不同的扩展,请看这里

标准化后的问题

完成此操作后,还有一个更常见的警告。

假设你master的已经是最新的并且已经标准化,然后你 checkout outdated-branch。很多时候,在签出该分支之后,git 会将许多文件标记为已修改。

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

于 2015-12-04T13:39:23.897 回答
4
git status --short|grep "^ *M"|awk '{print $2}'|xargs fromdos

解释:

  • git status --short

    这将显示 git 知道和不知道的每一行。不受 git 控制的文件在行首标有“?”。被修改的文件用 M 标记。

  • grep "^ *M"

    这仅过滤掉那些已修改的文件。

  • awk '{print $2}'

    这仅显示没有任何标记的文件名。

  • xargs fromdos

    这会从上一个命令中获取文件名,并通过实用程序“fromdos”运行它们以转换行尾。

于 2012-03-09T12:36:39.113 回答
4

以下是我如何使用git filter-branch. ^M需要使用+CTRL-V输入字符CTRL-M。我曾经dos2unix转换文件,因为这会自动跳过二进制文件。

$ git filter-branch --tree-filter 'grep -IUrl "^M" | xargs -I {} dos2unix "{}"'
于 2015-04-02T20:26:18.427 回答
3

“| xargs fromdos”从标准输入(文件find找到)中读取,并将其用作命令的参数,该命令fromdos转换行尾。(这些环境中的 fromdos 标准吗?我习惯于 dos2unix)。请注意,您可以避免使用 xargs(如果您有足够的文件而参数列表对于 xargs 来说太长,则特别有用):

find <path, tests...> -exec fromdos '{}' \;

或者

find <path, tests...> | while read file; do fromdos $file; done

我不完全确定您的错误消息。我成功地测试了这个方法。每个程序都在生产什么程序?您没有权限访问哪些文件/目录?但是,这里有一个猜测你可能是什么的尝试:

为脚本获取“找不到文件”错误的一种简单方法是使用相对路径 - 使用绝对路径。同样,如果您没有使脚本可执行(chmod +x),您可能会收到权限错误。

添加评论,我会尽力帮助您解决问题!

于 2009-10-02T17:50:31.383 回答
1

好吧......在cygwin下,我们没有容易获得的fromdos,如果你在修改文件的路径中有任何空格(我们有),那awk substeb就会在你的脸上爆炸,所以我不得不做一些不同的事情:

git status --short | grep "^ *M" | sed 's/^ *M//' | xargs -n 1 dos2unix

感谢@lloyd 提供了这个解决方案的大部分内容

于 2012-04-30T11:44:55.770 回答
-3

如果其他答案都不适合您,请按照以下步骤操作:

  1. 如果您在 Windows 上,请执行git config --global core.autocrlf true; 如果您在 Unix 上,请执行git config core.autocrlf input
  2. git rm --cached -r .
  3. 删除文件.gitattributes
  4. git add -A
  5. git reset --hard

那么你的本地现在应该是干净的。

于 2014-05-06T20:01:58.153 回答