试图用git filter-branch修复行尾,但没有运气

我已经被git的Windows / Linux行结束的问题困扰了。 看来,通过GitHub,MSysGit和其他来源,最好的解决方案是让您的本地回购设置使用Linux风格的行尾,但将core.autocrlf设置为true 。 不幸的是,我没有做到这一点,所以现在每次我改变线路结束时都是这样。

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

我已经在Windows上通过MSysGit和Mac OS X终端尝试了这一点。

现在, gitattributes的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状态显示,请在运行git add -u之前取消其文本属性。

manual.pdf -text

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

weirdchars.txt text

解决这个问题最简单的方法是做一个修复所有行结束的提交。 假设你没有任何修改的文件,那么你可以这样做,如下所示。

 # 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 . 

我处理线路结局的过程如下(在许多回购中进行了测试):

当创建一个新的回购:

  • .gitattributes与其他典型文件(如.gitignoreREADME.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跟踪哪些不同的扩展, 请看这里

正常化后的问题

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

说你的master已经是最新的,规范化,然后你结帐outdated-branch 。 经常检查出这个分支后,git将许多文件标记为已修改。

解决办法是做一个假提交( git add -A . && git commit -m 'fake commit' )然后git rebase master 。 重新绑定后,虚假承诺应该消失。

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

说明:

  • git status --short

    这显示了git是和不知道的每一行。 不在git控制下的文件在行首以'?'标记。 被修改的文件被标记为M.

  • grep "^ *M"

    这只滤出那些已被修改的文件。

  • awk '{print $2}'

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

  • xargs fromdos

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

“| xargs fromdos”从标准输入( find的文件find )中读取,并将其用作fromdos转换行的命令的fromdos ,转换行结束fromdos 。 (在这些环境中是从标准的?我习惯dos2unix)。 请注意,您可以避免使用xargs(如果您有足够的文件,xargs的参数列表太长,那么特别有用):

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

要么

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

我不完全确定你的错误信息。 我成功测试了这个方法。 什么程序生产每个? 你没有权限的文件/目录? 然而,这里有一个猜测你可能会是什么:

一个简单的方法来得到一个'文件未找到'错误的脚本是通过使用相对路径 – 使用绝对的。 同样,如果您还没有将脚本设置为可执行文件(chmod + x),则可能会出现权限错误。

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

好的…在cygwin下,我们没有很容易获得的fromdos,如果在修改过的文件的路径中有任何空格,那么awk子句就会在你的脸上炸开,所以我不得不这样做:

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

对这个解决方案的批量来说,我很感谢@lloyd

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

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

如果没有其他答案适用于您,请按以下步骤操作:

  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

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