从Git仓库中删除一个文件但不在本地文件系统中删除它

3832

我想从我的仓库中删除一个文件。

git rm file_to_remove.txt

这将从代码库中删除该文件,同时也会从本地文件系统中删除该文件。如何从代码库中删除该文件,而不删除我本地的文件副本?


4
如何在 Git 中停止跟踪和忽略文件的更改?原文链接:Stop tracking and ignore changes to a file in Git - user456814
52
值得注意的是,最受欢迎的答案对一些人来说是危险的。如果您正在使用远程仓库,则当您推送本地更改后,在其他地方拉取时,那些您从Git中删除的文件将会被删除。这在其中一个回复中提到了,但没有进行评论。 - RichieHH
2
请按照正确的方式操作:https://dev59.com/9lMH5IYBdhLWcg3w92It - goofology
1
重要警告:请在粘贴已接受的答案之前阅读此答案。https://dev59.com/lnM_5IYBdhLWcg3w-4dg#67793572 - Zahid Khan
据我所见,该链接的问题没有被接受的答案。那么正确的做法是什么?@goofology - a06e
正如您所看到的,根据所需的最终结果和适用于公共/共享存储库与私有存储库的后果,有许多不同的变体。关于链接的问题,我认为两个答案都可以 - 得票最高的是我的答案,但被接受的答案使用了一种在我编写解决方案时不存在的新方法。我没有尝试过被接受的答案。 - goofology
15个回答

5371

git rm 的文档说明如下:

如果给定了 --cached,则暂存的内容必须与分支的最新提交或磁盘上的文件匹配,从而允许仅从索引中删除该文件。

因此,对于单个文件:

git rm --cached file_to_remove.txt

并且对于单个目录:

git rm --cached -r directory_to_remove

205
因为它不像 svn rm --keep-local 那样自解释,所以很容易被忽视。 - Martin
144
我该如何保存远程服务器上的文件?我已经保存了本地文件,但是如果我从另一个服务器拉取或推送,该文件会被删除。我也为该文件添加了.gitignore文件,但它仍然被删除。 - spankmaster79
19
如果在运行了git rm命令后,你的代码库落后于某个提交,那么执行git pull命令仍会将那些文件删除。 - Petr Peller
18
值得注意的是,在运行答案中的命令后,您需要使用 git commit -m "Commit message"git push。如果您有任何其他暂存更改(通过 git status 检查),它们也将同时提交。 - Sinjai
24
由于这是最被广泛接受的答案并且不能正常工作,我将告诉你我所做的。 我使用命令 git rm --cached mylogfile.log 并从仓库中删除该文件。 为了避免在生产系统上丢失该文件,我会备份该文件并在此之后进行拉取。 正如之前提到的,该文件将被删除,需要从您的备份中复制回来。 这非常麻烦,但我没有找到更好的解决方法。 - Marcel Grolms
显示剩余6条评论

322

要从仓库中删除整个文件夹(例如 Resharper 文件),请执行以下操作:

git rm -r --cached folderName

我已经提交了一些resharper文件,但是不想让其他项目用户保留这些文件。


13
提醒未来的访问者:不要使用GUI界面来“同步”提交到仓库。这将会将文件重新拉回到你本地的代码库。你需要执行Git Push 仓库名 分支名来真正地从远程删除文件。 - RubberDuck

295

根据.gitignore从仓库中删除文件,而不会从本地文件系统中删除它们:

git rm --cached `git ls-files -i -c -X .gitignore`

对于 Windows Powershell:

git rm --cached $(git ls-files -i -c -X .gitignore)

8
无法在Windows上使用。git ls-files -i -X .gitignore可以使用,但我不知道如何将文件发送到'git rm'。你知道怎么做吗? - Erik Z
19
如果你使用 Git Bash 而不是 cmd 控制台,则可以在 Windows 上运行该程序。 - Andreas Zita
17
喜欢这个。它起作用了,只是我有一些文件名带有空格。我修改了这个解决方案: git ls-files -i -X .gitignore | xargs -I{} git rm --cached "{}"。请考虑修改或添加此解决方案到答案中,因为它是一个很棒的工具... - mpettis
1
我没有尝试过,但应该进行测试,看它是否会删除像 .gitkeep 这样在仓库中保留空文件夹的文件。例如,.gitignore 包含文件夹 uploads,并且强制存储库跟踪 .gitkeep。通过从 uploads 下的存储库中删除所有内容,也将删除 .gitkeep - Vladimir Vukanac
2
这个建议在PowerShell中完美地运行了:git rm --cached $(git ls-files -i -X .gitignore) - geekandglitter
显示剩余4条评论

130

根据我的回答:https://dev59.com/GG015IYBdhLWcg3w7wMW

仅从git仓库中删除文件夹/目录或文件,而不是从本地删除,请尝试以下3个简单步骤。


删除目录的步骤

git rm -r --cached File-or-FolderName
git commit -m "Removed folder from repository"
git push origin master

忽略某个文件夹在下一次提交中的步骤

要忽略某个文件夹在下一次提交中,只需在根目录下创建一个名为.gitignore的文件,并将该文件夹的名称放入其中。您可以放置任意数量的文件夹名称。

.gitignore文件将如下所示。

/FolderName

删除目录


2
当其他人拉取你的更改时,这会删除他们本地的文件吗? - Brad Mace

81

更通用的解决方案:

  1. 编辑 .gitignore 文件。

    echo mylogfile.log >> .gitignore

  2. 从索引中删除所有项目。

    git rm -r -f --cached .

  3. 重新构建索引。

    git add .

  4. 创建新的提交。

    git commit -m "已删除mylogfile.log文件"


3
这会真正删除文件吗? - Mr_and_Mrs_D
6
来自 GitHub?不是。如果你已经推送到 GitHub,它不会从该网站中删除它。但是它会更新你的本地 git 仓库。 - mAsT3RpEE
8
您删除的评论实际上被更多地清除了 :) 解决方案rm --cashed的问题在于,当一个人进行拉取时,它最终会删除文件 - 对吗?当人们说“从存储库中删除文件而不将其从本地文件系统中删除”的时候,这并不是他们想要的。现在为什么接受上述解决方案超出了我的理解 - 可能是因为OP自己工作,并且从未拉取过?不知道。我当然理解github的“一旦推送到那里就永远存在”的问题。 - Mr_and_Mrs_D
12
我的问题不在于 GitHub,而是当我的同事们 pull 时,文件会实际被删除。我不希望这个文件被删除。这在过去给我造成了巨大的问题。因此,我想知道是否真的有一个解决方案可以不删除文件。请参见已接受答案的评论:https://dev59.com/lnM_5IYBdhLWcg3w-4dg#20565682?noredirect=1#comment21117138_1143800 - Mr_and_Mrs_D
抱歉,我被卡住了。选项1:包含一个下载脚本,在拉取后添加文件。选项2:配置git update-index --assume-unchanged而不是git rm - mAsT3RpEE
显示剩余2条评论

78

27
回答应包括完成此任务所需的命令,而不是链接到其他网站。 - Florian Lemaitre
1
我还要注意到,我发现使用 git bfg repo cleaner 工具 更加简单和快速。 - Lubed Up Slug
1
链接已失效,这就是为什么你总是将信息放在你的帖子中而不只是链接到外部网站的原因。 - CapinWinky
@CapinWinky 感谢您提供的信息,我已经更新了答案并提供了最新的URL(虽然无法在答案中提供所有信息,因为这是一篇相当长的文章)。 - BoD

29
Git允许您通过假定它们未更改来忽略那些文件。这可以通过运行git update-index --assume-unchanged path/to/file.txt命令来完成。一旦将文件标记为这样,git将完全忽略该文件上的任何更改;在运行git status或git diff时不会显示它们,也永远不会被提交。
(摘自https://help.github.com/articles/ignoring-files
因此,不是删除它,而是永久忽略对它的更改。 我认为这仅在本地工作,因此,除非他们运行与上述相同的命令,否则同事仍然可以看到对它的更改。(虽然仍需要验证这一点。)
注意:这并不是直接回答问题,而是基于其他答案评论中的后续问题。

4
嗯,我这样做,但是如果其他人在仓库中对文件进行更改,那么文件可能会被覆盖。 - AlxVallejo
这是非常危险的,因为在这样的文件中任何冲突都会阻止您进行检出,而“假设”则会使您无法修复冲突。 - Agent_L
@Agent_L 运行 --no-assume-unchanged 命令会使其恢复吗?在这样做之前,只需将文件保存在某个地方即可?我很好奇,因为我的本地数据库设置文件被忽略了,但我还没有遇到你描述的情况,尽管当我遇到问题时可能只是删除并重新创建它,所以这对我来说不是问题。 - Rystraum
1
@Rystraum 是的,那就是我必须要做的。取消暂存并解决冲突。或者强制检出。如果您的数据库设置在源中没有更改,那就可以解释为什么缺少冲突。 - Agent_L

26
如果你只想取消对一个文件的跟踪,但是不从本地和远程仓库中删除它,请使用以下命令:

如果您想简单地 取消对文件的跟踪,而不从本地或者远端移除,请使用以下命令:

git update-index --assume-unchanged  file_name_with_path

11
虽然这是一个很好的答案,但需要注意的是,这并不是以 Git 中通常使用的方式“取消跟踪”文件。在 Git 中,未跟踪的文件是指未出现在存储库历史记录中并且从未出现过的文件。这个答案做的是将文件保留在存储库中,但防止 Git 注意到已对其进行更改。这有一些显着的区别--最重要的是,该文件仍然存在于其他人的本地版本库中。如果其他人对其进行更改,而你在 pull 时更新了本地版本库,则可以被覆盖而无需确认。 - Soren Bjornstad

17

忽略文件,从git中删除文件并更新git(以进行删除)

注意:这不涉及保护敏感信息的历史记录。

这个过程需要对git的操作有一些理解。随着时间的推移,我已经学会了一些操作,比如:

1)忽略文件

  • 添加或更新项目的 .gitignore 文件来忽略它们 - 在您的情况下,通常是父目录,例如 log/
  • 提交并推送该 .gitignore 文件更改(不确定是否需要推送,但无伤大雅)。

2)仅从git中删除文件

  • 使用 git rm --cached some_dir/ 仅从git中删除文件。
  • 检查它们在本地是否仍然存在(应该存在!)。

3)添加并提交该更改(本质上,这是一个“添加”删除文件的更改,尽管“添加”命令让人感到困惑!)

  • git add .
  • git commit -m "removal"

请参考以下问题了解为什么这是一个糟糕的答案:https://dev59.com/9lMH5IYBdhLWcg3w92It - Ilya Kolesnikov
@IlyaKolesnikov 我看了那个答案,但是使用第三步来提交删除更改可以解决大部分问题。 - Michael Durrant

8
以上的答案对我没有用。我使用filter-branch来删除所有已提交的文件。
使用以下命令从git存储库中删除文件:
git filter-branch --tree-filter 'rm  file'

使用以下命令从 Git 仓库中删除文件夹:

git filter-branch --tree-filter 'rm -rf directory'

这将在所有提交中删除该目录或文件。

您可以通过以下方式指定提交:

git filter-branch --tree-filter 'rm -rf directory' HEAD

或者一个范围:
git filter-branch --tree-filter 'rm -rf vendor/gems' t49dse..HEAD

要将所有内容推送到远程,您可以执行以下操作:

git push origin master --force

2
这个结合 git rm -r --cached NAME 的技巧可以将它从你的本地 git 仓库中移除,并防止它影响到后来拉取代码的任何人(通过从 git 中删除文件或目录的历史记录)。 - notbad.jpeg
1
这会重写 git 历史记录, 所以你需要在之后 push --force。我猜这有点超出了问题的范围。在一个公共的著名 repo 上,你不能像那样改变历史记录,因为已经克隆了该 repo 的每个人在拉取时都会遇到问题。 - Guillaume Perrot
从“git filter-branch”手册中可以看出,它有很多陷阱...请使用其他历史过滤工具,如git filter-repo。此外,如果您要重写历史记录,我想您可以在早期修改忽略文件,以便在新的历史记录中忽略已删除的项目? - Rodney

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