Git: 如何从索引中删除文件而不从任何存储库中删除文件

当你使用

git rm --cached myfile

它不会从本地文件系统中删除,这是目标。但是,如果您已经对该文件进行了版本控制并提交了该文件,将其推送到一个中央存储库,并在使用该命令之前将其拉入另一个存储库,那么它将从该系统中删除该文件。

有没有办法只从版本控制中删除文件而不从任何文件系统中删除它?

编辑: 我希望是澄清了。

113332 次浏览

执行 git rm --cached命令后,尝试将 myfile添加到 .gitignore文件中(如果不存在,则创建一个)。这应该告诉 git 忽略 myfile

.gitignore文件已经进行了版本控制,因此需要提交它并将其推送到远程存储库。

要从索引中删除该文件,请使用:

git reset mylife

这不应该影响您的本地副本或其他任何人的副本。

我不认为 Git 提交可以记录像“停止跟踪这个文件,但不要删除它”这样的意图。

实现这种意图将需要 Git 之外的任何存储库对合并(或重新基于)删除文件的提交进行干预。


保存副本,应用删除,还原

也许最简单的方法是告诉下游用户保存文件副本,删除文件,然后恢复文件。 如果他们通过 rebase 进行拉动,并“携带”对文件的修改,他们将得到冲突。要解决这些冲突,可以使用 git rm foo.conf && git rebase --continue(如果冲突提交除了对已删除的文件做了更改)或 git rebase --skip(如果冲突提交仅更改为已删除的文件)。

拉取删除文件的提交后将文件恢复为未跟踪

如果他们已经取消了你的删除提交,他们仍然可以恢复以前版本的文件与 吉特秀:

git show @{1}:foo.conf >foo.conf

或者使用 Git checkout(根据 William Pursell 的评论; 但是记得从索引中重新删除它!) :

git checkout @{1} -- foo.conf && git rm --cached foo.conf

如果他们已经采取了其他行动,因为拉您的删除(或者他们与基地拉到一个分离的 HEAD) ,他们可能需要的东西以外的 @{1}。他们可以使用 git log -g找到提交之前,他们取消您的删除。


在注释中,您提到要“取消跟踪,但保留”的文件是运行软件所需的某种配置文件(直接从存储库中取出)。

将文件保存为“默认”并手动/自动激活它

如果继续在存储库中维护配置文件的内容不是完全不可接受的,那么您可以将被跟踪的文件从(例如) foo.conf重命名为 foo.conf.default,然后在应用重命名提交后指示您的用户使用 cp foo.conf.default foo.conf。 或者,如果用户已经使用存储库的一些现有部分(例如,一个脚本或其他一些由存储库中的内容配置的程序(例如 Makefile或类似的))来启动/部署您的软件,您可以在启动/部署过程中加入一个默认机制:

test -f foo.conf || test -f foo.conf.default &&
cp foo.conf.default foo.conf

有了这样的默认机制,用户应该能够提交将 foo.conf重命名为 foo.conf.default的提交,而不需要做任何额外的工作。 另外,如果将来要进行额外的安装/存储库,则可以避免手动复制配置文件。

改写历史需要手动干预,无论如何..。

如果在存储库中维护内容是不可接受的,那么您可能希望使用类似于 git filter-branch --index-filter …的东西将其从历史中完全消除。 这相当于重写历史,需要对每个分支/存储库进行手动干预(请参阅 < em > git rebase manpage中的“从上游 Rebase 恢复”部分)。 配置文件所需的特殊处理只是从重写中恢复时必须执行的另一个步骤:

  1. 保存配置文件的副本。
  2. 从重写中恢复。
  3. 还原配置文件。

忽略它,防止复发

无论您使用哪种方法,您都可能希望在存储库中的 .gitignore文件中包含配置文件名,以便不会再有人无意中使用 git add foo.conf(这是可能的,但需要 -f/--force)。 如果你有不止一个配置文件,你可以考虑将它们全部“移动”到一个单独的目录中,忽略整个事情(“移动”我的意思是改变程序期望找到它的配置文件的位置,让用户(或启动/部署机制)将文件复制/移动到他们的新位置; 你显然不希望 去你的文件到一个你将忽略的目录中)。

我的解决方案是拉动另一个工作副本,然后做:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

它表示获取最新注释中的所有文件路径,并从 HEAD 的父节点检出它们。任务完成。

本周我也遇到了同样的问题,当时我不小心提交了一个构建文件,然后试图从一个共享存储库中删除一个构建文件,然后发生了这样的事情:

Http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

对我来说效果很好,至今没有提及。

git update-index --assume-unchanged <file>

要从版本控制中删除您感兴趣的文件,然后像往常一样使用所有其他命令。

git update-index --no-assume-unchanged <file>

如果你想把它放回去的话。

编辑: 请查看来自 Chris Johnsen 和 KPM 的评论,这只能在本地工作,如果其他用户不这样做,文件仍然在版本控制之下。接受的答案提供了更完整/正确的方法来处理这个问题。如果使用这种方法,也可以从链接中获得一些注释:

显然,这里有很多需要注意的地方。 如果您直接添加该文件,它将被添加到索引中。 打开此标志合并提交将导致合并失败 这样你就可以手动处理了。

上述解决方案在大多数情况下都能很好地工作。 但是,如果您还需要删除该文件的所有跟踪(即敏感数据,如密码) ,您还需要从整个提交历史中删除该文件,因为仍然可以从那里检索该文件。

这里有一个解决方案,它可以从整个提交历史中删除该文件的所有跟踪,就好像它从未存在过一样,但仍然可以将该文件保留在系统中。

Https://help.github.com/articles/remove-sensitive-data/

如果您位于本地 git 存储库中,并且不需要执行演练,那么实际上可以跳到步骤3。在我的例子中,我只需要步骤3和6,因为我已经创建了。Gitignore 文件,并且在我想要处理的存储库中。

要查看更改,可能需要访问存储库的 GitHub 根目录并刷新页面。然后通过链接导航到曾经拥有该文件的旧提交,以查看该文件现在已被删除。对我来说,只是刷新旧的提交页面并没有显示更改。

一开始看起来很吓人,但实际上很简单,而且非常有效! : -)

  1. git rm --cached remove_file
  2. 将文件添加到 gitignore
  3. git add .gitignore
  4. git commit -m "Excluding"
  5. 玩得开心;)