我在我的存储库中有一些文件应该被忽略,我将它们添加到.gitignore,但是,当然,它们不会从我的存储库中删除。
所以我的问题是,是否有一个神奇的命令或脚本使用过滤器分支,可以重写我的历史,并轻松删除所有这些文件?或者只是一个创建提交并删除它们的命令?
我在我的存储库中有一些文件应该被忽略,我将它们添加到.gitignore,但是,当然,它们不会从我的存储库中删除。
所以我的问题是,是否有一个神奇的命令或脚本使用过滤器分支,可以重写我的历史,并轻松删除所有这些文件?或者只是一个创建提交并删除它们的命令?
当前回答
通过使用sed操作.gitignore语句的输出,我做了一个非常简单的解决方案:
Cat .gitignore | sed '/^#。* / d ' | sed ' / ^ \ s *美元/ d ' | sed ' s / ^ / git rm - r / | bash
解释:
打印.gitignore文件 从打印中删除所有注释 删除所有空行 在行首添加'git rm -r ' 执行每一行。
其他回答
不管操作系统是什么,一个更简单的方法是
git rm -r --cached .
git add .
git commit -m "Drop files from .gitignore"
你基本上删除并重新添加所有文件,但是git add会忽略.gitignore中的文件。
使用——cached选项将文件保存在文件系统中,这样就不会从磁盘中删除文件。
注意: 有些人在评论中指出,你将失去所有文件的历史记录。我在MacOS上用git 2.27.0进行了测试,结果不是这样。如果你想检查发生了什么,在你提交之前检查你的git diff HEAD~1。
由于.gitignore中的文件没有被跟踪,您可以使用git clean命令递归地删除不受版本控制的文件。
使用git clean -xdn执行一个演练,看看将删除什么。 然后使用git clean -xdf来执行它。
基本上,git clean -h或man git-clean(在unix中)将为您提供帮助。
注意,该命令还将删除暂存区域中不存在的新文件。
您可以手动从存储库中删除它们:
git rm --cached file1 file2 dir/file3
或者,如果你有很多文件:
git rm --cached `git ls-files -i -c --exclude-from=.gitignore`
但是这在Windows上的Git Bash中似乎不起作用。它产生一个错误消息。以下方法效果更好:
git ls-files -i -c --exclude-from=.gitignore | xargs git rm --cached
在Windows上的PowerShell工作得更好(处理路径和文件名中的空格):
git ls-files -i -c --exclude-from=.gitignore | %{git rm --cached $_}
关于在没有这些文件的情况下重写整个历史,我非常怀疑是否有自动的方法来做到这一点。 我们都知道改写历史不好,不是吗?:)
通过使用sed操作.gitignore语句的输出,我做了一个非常简单的解决方案:
Cat .gitignore | sed '/^#。* / d ' | sed ' / ^ \ s *美元/ d ' | sed ' s / ^ / git rm - r / | bash
解释:
打印.gitignore文件 从打印中删除所有注释 删除所有空行 在行首添加'git rm -r ' 执行每一行。
这个解决方案增加了回车符(我是一个WSL用户,所以这很重要)和圆括号转义(有时对LaTeX用户很重要,例如*.synctex(busy))。
受到Scott解决方案的启发:
cat .gitignore | sed "s/\r//" | sed -r "/^(#.*|\s*)$/d" | sed -r "s/([()])/\\\\\1/g" | sed "s/^/git rm -r /" | bash
Remove: carriage returns (s/\r//). Remove lines containing: comments (/^#.*$/), empty line groups (/^\s*$/, matches whitespace or empty line). Notice the pipe | character, this is standard regex, and requires -r (although I believe -E also works). Replace: parenthesis /([()])/ with its escaped version \\\1, \1 matches the group, in this case it means [()], or ( or ), whatever was matched. Notice the g flag, this is to match (and replace) all parenthesis. Could be rewritten as "s/(\(|\))/\\\\\1/g" if you're into that. Prepend git rm -r
替换看起来像s/$old/$new/$flags。删除看起来像/$old/d。Prepending替换/^/。你可以通过替换/$/来追加。当然,有些字符是转义的,因为据我所知,你不能在bash中创建原始字符串。最后,这一行可以压缩,但为了可读性,我选择将其展开。
我看到有人质疑(在Scott的解决方案中)sed是直截了当的。我喜欢把这个方法看作是最基本最简单的方法,这很好,因为如果你需要它的变化,你可以当场做出来。如果有的话,这是一个练习正则表达式的好借口。