尝试使用git filter-branch修复行尾,但没有成功

sdnqo3pr  于 2022-11-20  发布在  Git
关注(0)|答案(9)|浏览(146)

我一直被git的Windows/Linux行尾问题困扰着。通过GitHub、MSysGit和其他来源,似乎最好的解决方案是将本地repos设置为使用Linux风格的行尾,但将core.autocrlf设置为true。不幸的是,我做得不够早,所以现在每次我修改行尾时,行尾都被打断了。
我以为我在这里找到了答案,但我无法让它为我工作。我的Linux命令行知识充其量是有限的,所以我甚至不知道“xargs fromdos”行在他的脚本中做了什么。我一直收到消息说没有这样的文件或目录存在,当我设法将它指向一个现有的目录时,它告诉我我没有权限。
我已经在Windows和Mac OS X终端上用MSysGit试过了。

bvn4nwqk

bvn4nwqk1#

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

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

0mkxixxg2#

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之前取消设置它们的text属性。
manual.pdf -text
相反,git没有检测到的文本文件可以手动启用规范化。
weirdchars.txt text
这利用了2018年1月发布的git v2.16.0中添加的新--renormalize标志。
但如果您有“未暂存的已删除文件”,则可能会失败,因此请先暂存这些文件,例如:

git ls-files -z --deleted | xargs -0 git add

对于旧版本的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"
pwuypxnk

pwuypxnk3#

我处理行尾的程序如下(在许多回购协议中经过了实战检验):

创建新存储库时:

  • .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在当前repo中跟踪哪些不同的扩展,look here

标准化后的问题

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

假设你的master已经是最新的并且规范化了,然后你 checkout 了outdated-branch。通常在 checkout 这个分支后,git会把很多文件标记为修改过。
解决方案是先执行伪提交(git add -A . && git commit -m 'fake commit'),然后执行git rebase master

7nbnzgx9

7nbnzgx94#

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

说明:

  • git status --short

这会显示每一行被git控制和不被git控制的文件。不受git控制的文件会在行首标上'?'。被修改的文件会标上M。

  • grep "^ *M"

这只会筛选出已修改的档案。

  • awk '{print $2}'

这只显示文件名,不显示任何标记。

  • xargs fromdos

这将从前面的命令中获取文件名,并通过实用程序“fromdos”运行它们以转换行尾。

nzk0hqpo

nzk0hqpo5#

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

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

rks48beu6#

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

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

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

我不能完全确定您的错误消息。我成功地测试了这个方法。每个错误消息都是由什么程序生成的?您没有权限访问哪些文件/目录?不过,下面我们来猜猜您的错误消息可能是什么:
一个简单的方法是使用相对路径--使用绝对路径--来得到一个“找不到文件”的错误。同样的,如果你没有把你的脚本设置为可执行的(chmod +x),你也会得到一个权限错误。
添加评论,我会尽量帮助你解决它!

3vpjnl9f

3vpjnl9f7#

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

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

感谢@Lloyd提供的大量解决方案

ecfdbz9o

ecfdbz9o8#

我在我的一个repo中遇到了同样的问题。如果你同时使用windows和linux系统进行相同的代码repo,并且同时进行拉和推,试试这个:
首先,在windows环境下按照如下方式设置git config:

git config --global core.autocrlf true

这将确保在写入对象数据库时将CRLF转换为LF,然后在写出到工作目录时再次将LF替换为CRLF。因此,您的存储库将只使用一种类型的行尾,并且在本地Windows系统上使用Windows行尾。
对于linux/MAC,按如下方式设置git配置:

git config --global core.autocrlf input

这将确保在写入对象数据库时将CRLF转换为LF,但不会执行相反的操作,保留Linux/MAC所需的LF。
对于Linux/MAC上已经存在的错误行尾,请使用dos2unix
对于MAC:

brew install dos2unix # Installs dos2unix Mac
find . -type f -exec dos2unix {} \; # recursively removes windows related stuff

对于Linux:

sudo apt-get install -y dos2unix # Installs dos2unix Linux
sudo find . -type f -exec dos2unix {} \; # recursively removes windows related stuff

希望这能解决你的问题。

nbnkbykc

nbnkbykc9#

如果其他答案都不适合您,请按照以下步骤操作:
1.如果您使用的是Windows,请执行git config --global core.autocrlf true;如果您在Unix上,请执行git config core.autocrlf input
1.运行git rm --cached -r .
1.删除文件.gitattributes
1.运行git add -A
1.运行git reset --hard
那你的本地人现在应该是清白的了。

相关问题