在使用Git时,开发人员通常会在他们的存储库中添加许多文件,这样他们就会意识到他们想稍后删除这些文件。
在Git上删除文件常常是一个令人困惑的问题:我需要从仓库中删除它们,还是应该从文件系统中删除它们?
如果您在以前的提交中引入了一个文件,是否有方法从仓库中的所有提交中删除该文件?
在本教程中,俺将带大家了解如何轻松地在Git上删除文件,无论是从Git存储库还是从文件系统。
使用git rm删除文件
在Git存储库中删除文件的最简单方法是执行“git rm”命令并指定要删除的文件。
$ git rm <file>
$ git commit -m "Deleted the file from the git repository"
$ git push
注意,通过使用“git rm”命令,文件也将从文件系统中删除。
另外,您必须提交您的更改,“git rm”不会从git索引中删除该文件,除非您提交该文件。
像往常一样,让我们通过一个简单的例子来说明我们刚才描述的命令。
在我当前的存储库中,有三个名为“file1”、“file2”和“file3”的文件,我想从我的Git存储库中删除“file1”文件。
通过使用“git ls-tree”命令,可以看到当前分支上跟踪的文件。
$ git ls-tree -r master
为了从Git存储库和文件系统中删除文件“file1”,我们将使用文件的名称执行“git rm”命令。
$ git rm file1
rm 'file1'
正确执行后,会返回以下信息:
可以看到,通过执行“git rm”命令,一个“deleted”操作被添加到要提交的更改中。
这意味着文件已经从文件系统中删除,但还没有从索引中删除。
为了使更改有效,您必须提交更改并将其推到远程存储库。
现在应该从文件系统和索引中删除该文件,您可以通过重新执行“git ls-tree”命令来验证它,以便在当前索引中列出文件。
祝贺您,您成功地从Git存储库中删除了一个文件。
在Git上递归删除文件
为了在Git上递归地删除文件,必须使用“git rm”命令并使用“-r”选项进行递归,并指定要删除的文件列表。
$ git rm -r <folder>
$ git commit -m "Deleted the folder from the repository"
$ git push
当您需要删除整个目录或目录中的文件子集时,这特别方便。
例如,假设我们的Git存储库有一个名为“folder1”的文件夹,其中包含两个文件。
为了删除该文件夹以及其中包含的文件,我们将使用“-r”选项执行“git rm”命令。
$ git rm -r folder1
类似地,不要忘记更改在提交时有效,而不是在提交之前。
恭喜!已成功地从Git存储库中删除了整个文件夹。
只在Git存储库中删除文件
在某些情况下,您希望从Git存储库而不是文件系统中删除文件,您必须使用“-cached”选项执行“git rm”命令。
$ git rm --cached <file>
$ git commit -m "Deleted file from repository only"
$ git push
回到我们的示例,我们目前在工作文件夹中有两个文件:file2和file3。
让我们假设我们想要从存储库中删除文件“file2”,但是我们想把它保存在文件系统中。
要实现这一点,只需执行带有“-cached”选项的“git rm”命令。
$ git rm --cached file2
可以看到,在执行“git rm”命令之后,文件仍然在文件系统中。
在提交更改之前,您可能会注意到“git status”命令将文件添加到要提交的更改中,以及未跟踪文件列表中。
因为你的文件不再被跟踪,因为你的前一个删除的结果。
现在,如果文件不在Git存储库的“未跟踪文件”下列出,请确保将其添加到Git忽略文件中。
$ touch .gitignore
# Content of the gitignore file
file2
从Git历史记录中删除文件
在某些情况下,您希望从整个Git历史记录中删除文件。
例如,如果您提交了一个文件,其中包含您想要删除的密码或一些敏感信息,则可能会出现这种情况。
为了从Git历史记录中删除文件,您必须使用“git filter-branch”命令,并指定要在Git历史记录的所有分支上执行的命令。
最后,您需要指定要执行更改的修订:我们将选择HEAD(提醒一下,HEAD是存储库的最后一次提交)。
在本例中,要执行的Git命令是我们前面描述的“git rm ”命令。
$ git filter-branch --force --index-filter --prune-empty "git rm --cached --ignore-unmatch <path_to_file>" HEAD
由于该命令相当复杂,让我们对所使用的所有选项进行分解:
- -force:相当自解释,它强制过滤器分支启动,即使它可能不想(根据文档,因为它可以包含临时目录)
- -index-filter:用于重写索引的选项,这正是我们在文件删除的情况下想要的
- “git rm”命令:在历史上匹配的所有分支、修订和提交上执行的命令,在这种情况下,它将从存储库中删除文件并忽略不匹配的文件
- -prune-empty:避免在没有文件的存储库中出现空提交,此选项将自动删除提交.
在本例中,假设我们想删除存储库中包含的文件“file1”。
我们可以执行下面命令:
$ git filter-branch -f --prune-empty --index-filter "git rm -r --cached --ignore-unmatch ./file1" HEAD
如果历史记录中包含许多文件,此命令可能需要一段时间,但最终删除的文件将不再出现在Git历史记录中。
您可以使用“git log”命令进行检查,但是如果需要,应该删除链接到已删除文件的提交。