试图用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
与其他典型文件(如.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跟踪哪些不同的扩展, 请看这里
正常化后的问题
一旦完成,还有一个更常见的警告。
说你的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 "{}"'
如果没有其他答案适用于您,请按以下步骤操作:
- 如果你在Windows上,请执行
git config --global core.autocrlf true
; 如果你在Unix上,请做git config core.autocrlf input
- 运行
git rm --cached -r .
- 删除文件
.gitattributes
- 运行
git add -A
- 运行
git reset --hard
那么你的本地应该现在干净。