小编典典

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

all

当你使用

git rm --cached myfile

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

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

编辑:澄清,我希望。


阅读 70

收藏
2022-08-27

共1个答案

小编典典

我不认为 Git 提交可以记录诸如“顶级跟踪此文件,但不要删除它”之类的意图。

制定这样的意图将需要在 Git 之外的任何存储库中进行干预,这些存储库合并(或变基到)删除文件的提交。


保存副本、应用删除、恢复

可能最简单的做法是告诉您的下游用户保存文件的副本,拉取您的删除,然后恢复文件。如果他们通过 rebase
拉取并且正在对文件进行“arrying”修改,他们将发生冲突。要解决此类冲突,请使用git rm foo.conf && git rebase --continue(如果冲突提交除了已删除文件之外还有更改)或git rebase --skip(如果冲突提交仅更改为已删除文件)。

在提交删除文件后将文件恢复为未跟踪

如果他们已经提取了您的删除提交,他们仍然可以使用 git
show

恢复文件的先前版本:

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

或使用 git checkout (根据 William Pursell
的评论;但请记住将其从索引中重新删除!):

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

如果他们在删除您的删除后采取了其他操作(或者他们正在使用 rebase 拉入分离的 HEAD),他们可能需要@{1}. 他们可以git log -g在删除您的删除之前找到提交。


在评论中,您提到要“不跟踪,但保留”的文件是运行软件所需的某种配置文件(直接来自存储库)。

将文件保留为“错误”并手动/自动激活它

如果继续在存储库中维护配置文件的内容并非完全不可接受,您可以将跟踪的文件从 (eg)
重命名foo.conffoo.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
.
这相当于重写历史记录,这将需要对每个分支/存储库进行手动干预(请参阅git rebase 手册页中的“从上游 Rebase 中恢复”部分)。配置文件所需的特殊处理只是从重写中恢复时必须执行的另一个步骤:

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

忽略它以防止再次发生

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

2022-08-27