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

时间:2009-10-02 17:12:49

标签: git newline msysgit line-endings

我被git用Windows / Linux行结束问题所困扰。看来,通过GitHub,MSysGit和其他来源,最好的解决方案是将本地存储库设置为使用linux样式的行结尾,但将core.autocrlf设置为true。不幸的是,我没有及早做到这一点,所以现在每次我改变时,行结尾都会被剔除。

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

我在Windows上通过Mac OS X终端尝试使用MSysGit。

8 个答案:

答案 0 :(得分:383)

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

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

答案 1 :(得分:183)

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 -text

     

相反,git的文本文件   未检测到可以正常化   手动启用。

     

weirdchars.txt text

这利用了在2018年1月发布的git v2.16.0中添加的新--renormalize标志。对于旧版本的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"

答案 2 :(得分:10)

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

创建新的回购时:

  • .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跟踪的不同扩展名,look here

规范化后的问题

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

假设您的master已更新并已标准化,然后结帐outdated-branch。通常在检查出该分支后,git会将许多文件标记为已修改。

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

答案 3 :(得分: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'运行它们以转换行尾。

答案 4 :(得分: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),则可能会收到权限错误。

添加评论,我会尝试帮助您解决问题!

答案 5 :(得分:2)

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

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

答案 6 :(得分:1)

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

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

对@lloyd的大部分解决方案感到荣幸

答案 7 :(得分:-2)

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

  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
  6. 然后你的当地人现在应该干净。