试图用 git filter-branch 修复行尾,但没有运气
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1510798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Trying to fix line-endings with git filter-branch, but having no luck
提问by Brian Donahue
I have been bitten by the Windows/Linux line-ending issue with git. It seems, via GitHub, MSysGit, and other sources, that the best solution is to have your local repos set to use linux-style line endings, but set core.autocrlf
to true
. Unfortunately, I didn't do this early enough, so now every time I pull changes the line endings are borked.
我一直被 git 的 Windows/Linux 行尾问题所困扰。通过 GitHub、MSysGit 和其他来源,似乎最好的解决方案是将本地存储库设置为使用 linux 样式的行结尾,但设置core.autocrlf
为true
. 不幸的是,我没有足够早地这样做,所以现在每次我拉更改时,行尾都会被打断。
I thought I had found an answer herebut I can't get it to work for me. My Linux command line knowledge is limited at best, so i am not even sure what the "xargs fromdos" line does in his script. I keep getting messages about no such file or directory existing, and when I manage to point it to an existing directory, it tells me I don't have permissions.
我以为我在这里找到了答案,但我无法让它对我来说有效。我的 Linux 命令行知识充其量是有限的,所以我什至不确定“xargs fromdos”行在他的脚本中做了什么。我不断收到有关不存在此类文件或目录的消息,当我设法将其指向现有目录时,它告诉我我没有权限。
I've tried this with MSysGit on Windows and via the Mac OS X terminal.
我已经在 Windows 上使用 MSysGit 并通过 Mac OS X 终端尝试过这个。
采纳答案by Russ Egan
The git documentation for gitattributesnow documents another approach for "fixing" or normalizing all the line endings in your project. Here's the gist of it:
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"
If any files that should not be normalized show up in git status, unset their text attribute before running git add -u.
manual.pdf -text
Conversely, text files that git does not detect can have normalization enabled manually.
weirdchars.txt text
如果任何不应规范化的文件出现在 git status 中,请在运行 git add -u 之前取消设置它们的文本属性。
manual.pdf -text
相反,git 未检测到的文本文件可以手动启用规范化。
weirdchars.txt text
This leverages a new --renormalize
flag added in git v2.16.0, released Jan 2018. For older versions of git, there are a few more steps:
这利用了--renormalize
2018 年 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"
回答by CB Bailey
The easiest way to fix this is to make one commit that fixes all the line endings. Assuming that you don't have any modified files, then you can do this as follows.
解决此问题的最简单方法是进行一次修复所有行结尾的提交。假设您没有任何修改过的文件,那么您可以按如下方式执行此操作。
# 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 .
回答by jakub.g
My procedure for dealing with the line endings is as follows (battle tested on many repos):
我处理行尾的程序如下(在许多 repos 上进行了战斗测试):
When creating a new repo:
创建新仓库时:
- put
.gitattributes
in the very first commit along with other typical files as.gitignore
andREADME.md
- 将
.gitattributes
第一个提交与其他典型文件一起作为.gitignore
和README.md
When dealing with an existing repo:
处理现有仓库时:
- 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
相应 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会发现更多的文件需要重新规范化!
In .gitattributes
I declare all text files explicitly as having LF EOL since generally Windows tooling is compatible with LF while non-Windows tooling is not compatible with CRLF(even many nodejs command line tools assume LF and hence can change the EOL in your files).
在.gitattributes
我明确声明所有文本文件都具有 LF EOL,因为通常 Windows 工具与 LF 兼容,而非 Windows 工具与 CRLF 不兼容(甚至许多 nodejs 命令行工具都假定为 LF,因此可以更改文件中的 EOL)。
Contents of .gitattributes
的内容 .gitattributes
My .gitattributes
usually looks like:
我.gitattributes
通常看起来像:
*.html eol=lf
*.js eol=lf
*.json eol=lf
*.less eol=lf
*.md eol=lf
*.svg eol=lf
*.xml eol=lf
To figure out what distinct extensions are tracked by git in the current repo, look here
要找出当前存储库中 git 跟踪哪些不同的扩展,请查看此处
Issues after normalization
规范化后的问题
Once this is done, there's one more common caveat though.
完成此操作后,还有一个更常见的警告。
Say your master
is already up-to-date and normalized, and then you checkout outdated-branch
. Quite often right after checking out that branch, git marks many files as modified.
假设您master
已经是最新的并且已经标准化,然后您结帐outdated-branch
. 经常在检出该分支后,git 将许多文件标记为已修改。
The solution is to do a fake commit (git add -A . && git commit -m 'fake commit'
) and then git rebase master
. After the rebase, the fake commit should go away.
解决方案是做一个假的 commit( git add -A . && git commit -m 'fake commit'
),然后git rebase master
. 在 rebase 之后,虚假提交应该消失。
回答by pfrenssen
Here's how I fixed all line endings in the entire history using git filter-branch
. The ^M
character needs to be entered using CTRL-V
+ CTRL-M
. I used dos2unix
to convert the files since this automatically skips binary files.
这是我使用git filter-branch
. 该^M
字符需要使用输入CTRL-V
+ CTRL-M
。我曾经dos2unix
转换文件,因为这会自动跳过二进制文件。
$ git filter-branch --tree-filter 'grep -IUrl "^M" | xargs -I {} dos2unix "{}"'
回答by Lloyd Moore
git status --short|grep "^ *M"|awk '{print }'|xargs fromdos
Explanation:
解释:
git status --short
This displays each line that git is and is not aware of. Files that are not under git control are marked at the beginning of the line with a '?'. Files that are modified are marked with an M.
grep "^ *M"
This filters out only those files that have been modified.
awk '{print $2}'
This shows only the filename without any markers.
xargs fromdos
This takes the filenames from the previous command and runs them through the utility 'fromdos' to convert the line-endings.
git status --short
这将显示 git 知道和不知道的每一行。不受 git 控制的文件在行首用“?”标记。被修改的文件用 M 标记。
grep "^ *M"
这仅过滤掉那些已修改的文件。
awk '{print $2}'
这仅显示没有任何标记的文件名。
xargs fromdos
这将从上一个命令中获取文件名,并通过实用程序“fromdos”运行它们以转换行尾。
回答by Cascabel
The "| xargs fromdos" reads from standard input (the files find
finds) and uses it as arguments for the command fromdos
, which converts the line endings. (Is fromdos standard in those enviroments? I'm used to dos2unix). Note that you can avoid using xargs (especially useful if you have enough files that the argument list is too long for xargs):
“| xargs fromdos”从标准输入(文件find
找到)读取并将其用作命令的参数,该命令fromdos
转换行尾。(这些环境中的 fromdos 是标准的吗?我习惯了 dos2unix)。请注意,您可以避免使用 xargs(如果您有足够多的文件而参数列表对于 xargs 来说太长,则尤其有用):
find <path, tests...> -exec fromdos '{}' \;
or
或者
find <path, tests...> | while read file; do fromdos $file; done
I'm not totally sure about your error messages. I successfully tested this method. What program is producing each? What files/directories do you not have permissions for? However, here's a stab at guessing what your it might be:
我不完全确定您的错误消息。我成功地测试了这个方法。分别制作什么节目?您对哪些文件/目录没有权限?然而,这里有一个猜测你可能是什么的尝试:
One easy way to get a 'file not found' error for the script is by using a relative path - use an absolute one. Similarly you could get a permissions error if you haven't made your script executable (chmod +x).
获取脚本“找不到文件”错误的一种简单方法是使用相对路径 - 使用绝对路径。同样,如果您没有使脚本可执行 (chmod +x),您可能会收到权限错误。
Add comments and I'll try and help you work it out!
添加评论,我会尽力帮助您解决问题!
回答by Anton K
okay... under cygwin we don't have fromdos easily available, and that awk substeb blows up in your face if you have any spaces in paths to modified files (which we had), so I had to do that somewhat differently:
好的...在 cygwin 下,我们没有容易获得的 fromdos,如果修改文件的路径中有任何空格(我们有),那么 awk substeb 就会在你面前炸毁,所以我不得不做一些不同的事情:
git status --short | grep "^ *M" | sed 's/^ *M//' | xargs -n 1 dos2unix
kudos to @lloyd for the bulk of this solution
感谢@lloyd 提供的大部分解决方案
回答by zs2020
Follow these steps if none of other answers works for you:
如果其他答案都不适合您,请按照以下步骤操作:
- If you are on Windows, do
git config --global core.autocrlf true
; if you are on Unix, dogit config core.autocrlf input
- Run
git rm --cached -r .
- Delete the file
.gitattributes
- Run
git add -A
- Run
git reset --hard
- 如果您使用的是 Windows,请执行以下操作
git config --global core.autocrlf true
;如果您使用的是 Unix,请执行git config core.autocrlf input
- 跑
git rm --cached -r .
- 删除文件
.gitattributes
- 跑
git add -A
- 跑
git reset --hard
Then your local should be clean now.
那么你的本地现在应该是干净的。