Git删除多个文件?

31
如何在不手动输入所有文件的完整路径到"git rm"命令中的情况下轻松删除多个文件?我有很多修改过的文件需要保留,因此无法删除所有已修改的文件。
另外,是否可以在不手动输入"git checkout -- /path/to/file"命令的情况下还原多个文件的更改?
11个回答

49
你可以在 git rm 中使用通配符。
例如:
git rm *.c

或者你可以将要删除的所有文件名写入另一个文件中,比如说filesToRemove.txt

path/to/file.c
path/to/another/file2.c
path/to/some/other/file3.c
你可以自动化这个过程:
find . -name '*.c' > filesToRemove.txt

打开文件并检查文件名(确保它是正确的)。

然后:

cat filesToRemove.txt | xargs git rm

或者:

for i in `cat filesToRemove.txt`; do git rm $i; done

查看xargs的手册以获取更多选项(特别是如果要处理太多文件时)。


1
他正在使用Windows操作系统,并且使用Windows的shell。 - jmlane
这对于一个大约需要3秒钟完成的事情来说过于复杂了。 - Tower
1
基本上就是使用 "git rm <file>..." 命令,然后你需要传递所有文件名。除非 Git 能读取你的思维,否则这是最快的方法。 - Manish
1
请注意,git rm *.c 看起来是递归的。 - Gauthier
使用 git ls-files 而不是 find 通常更好,因为 find 可能会找到尚未被 git 跟踪的文件,并导致管道失败。 - Dan Field
1
在 Mac 上,由于某些原因,我不得不使用引号 git rm '*.c'。 - Nick Manning

13

使用任何其他方法(例如资源管理器),删除它们,然后运行git add -A即可。至于还原多个文件,您也可以检出一个目录。


1
本页面上最简单的方法。 - Jon
我来这里是为了寻找比资源管理器更简单的方法。如果我能够使用Bash中的递归搜索找到所有要删除的文件,我宁愿不使用资源管理器并返回Git Bash以完成它。类似这样的命令“几乎”可以工作: find . -name "debug" -exec bash -c 'file={}; git rm $file' ; 只是使用相对路径。 - Sonic Soul
注意不要使用-A参数。 "如果在使用-A选项时没有给出<pathspec>,则会更新整个工作树中的所有文件(旧版本的Git仅限于当前目录及其子目录)"使用-A参数可能会暂存您尚未准备好暂存的更改。 - Kay

5

我发现git rm处理通配符很麻烦。Find命令可以在一行中完成操作: find . -name '*.c' -exec git rm {} \; 这里的{}会被替换成文件名。find的好处是它可以过滤大量的文件属性,而不仅仅是名称。


4
在Windows 10上,使用Git Bash,从文件结构中的.gitignore位置开始。
git rm -r --cached some_directory/

我刚刚使用了这个方法来递归地忽略整个目录。 以下是我在.gitignore文件中的设置:

# Use .gitignore to ignore a directory and its contents #
/some_directory/ 

3

简单的方法:

  • 在文件浏览器中删除文件
  • 使用git ls-files --deleted | xargs git add将它们加入到暂存区。一旦你推送,它们就会从远程仓库中删除。

Git方式: 参考@CpILL所说的(https://dev59.com/U2kw5IYBdhLWcg3w9_Qi#34889424) 使用

  • find . -name 'DeleteMe*.cs' -exec git rm {} \;

你可以利用通配符。


2

如果您想一次删除多个文件,可以查看这里的答案。

您可以删除不需要的文件,然后运行此命令:git rm $(git ls-files --deleted)


1
您可以简单地使用:

git add -u

来自官方文档

-u --update

仅更新已经存在匹配项的索引。这样会删除并修改索引条目以匹配工作树,但不会添加新文件。

如果在使用-u选项时未给出任何,则将更新整个工作树中的所有已跟踪文件(旧版本的Git只会限制更新当前目录及其子目录)。

换句话说,就是来自这个答案

它会从整个工作树中更新或删除先前跟踪的文件,但不会添加新文件。


2
请在您的回答中添加更多细节。 - Jayan

1
在 POSIX 系统上,您可以创建一个 shell glob,以匹配所有所需的文件,然后将其简单地传递给 git rmgit checkout --。在 Windows 上,cmd.exe 和 PowerShell 不包括 globbing,并将其分配给应用程序(从我所读的内容来看,git 不会对文件执行此操作)。您需要使用 Windows 命令或脚本来准备文件列表,并将其适当地传递到 git 命令中,以获得类似的效果。
任何您用于将文件列表传递给 shell 命令的策略都适用于接受文件路径的 git 命令。

哦,Windows的cmd.exe和PowerShell不支持globbing,至少我所知道的是git for Windows也没有包含这个功能,因为它会破坏树/分支/提交的globbing(或者我读到的是这样)。你需要探索Windows的shell方法来进行文件路径匹配。 - jmlane

1

或者您可以将所有要删除的文件名写入另一个文件中,例如filesToRemove.txt

这是一个好方法,使用Git 2.26(2020年第二季度)之后,因为"git rm"和"git stash"学会了新的"--pathspec-from-file"选项。

所以不再需要使用for i incat filesToRemove.txt; do git rm $i; done

一个简单的git rm --pathspec-from-file=filesToRemove.txt就足够了。

请查看 commit 8a98758, commit 8c3713c, commit 3f3d806, commit b229091, commit 0093abc, commit 2b7460d, commit 5f393dc (2020年2月17日),以及 commit 6a7aca6 (2020年1月16日) 由 Alexandr Miloslavskiy (SyntevoAlex) 提交。
(由 Junio C Hamano -- gitster -- 合并于 commit 9b7f726, 2020年3月9日)

rm:支持--pathspec-from-file选项

签名作者:Alexandr Miloslavskiy

为了简单起见,做出以下决定:

不允许在参数和文件中同时传递pathspec。

需要对if (!argc)块进行调整:

这段代码实际上意味着"pathspec不存在"。
以前,pathspec只能来自命令行参数,因此测试argc是一种有效的测试pathspec是否存在的方法。但是,使用--pathspec-from-file后,这种情况不再成立。

在整个--pathspec-from-file的过程中,我试图使其行为与在命令行上提供pathspec非常接近,以便从一个切换到另一个不会有任何惊喜。

然而,在空的--pathspec-from-file的情况下向用户抛出用法信息会让人困惑,因为“用法”(即argc/argv数组)没有问题。

另一方面,在旧情况下也向我展示用法感觉不好。虽然这不是很难理解,但我(作为用户)从来不喜欢将我的命令行与“用法”进行比较,试图找到差异。由于已经知道错误是什么,向用户提供特定的错误信息会感觉好得多。

从提交7612a1ef(“git-rm:honor -n flag”2006-06-09,git v1.4.0)来看,在这种情况下显示用法并不重要(补丁是为了避免段错误),而且它不符合其他命令对空pathspec的反应方式(例如使用自定义消息的git add)。

因此,我决定在两种情况下显示新的错误文本。
为了继续尽早测试错误,我将parse_pathspec()移到更高的位置。现在它发生在read_cache()/hold_locked_index()/setup_work_tree()之前,这不应该引起任何问题。


0
你也可以尝试使用Cygwin,因为它在Windows上提供了大部分Unix/Linux/*BSD功能。Cygwin包括Bash shell和find(1)等上面提到的其他工具。(我通常同时在Windows 7上使用2-4个Cygwin mintty终端,因为我发现Cygwin非常方便。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接