当你使用
git rm --cached myfile
它不会从本地文件系统中删除,这是目标。但是,如果您已经对文件进行了版本控制并提交,将其推送到中央存储库,并在使用该命令之前将其拉入另一个存储库,它将从该系统中删除该文件。
有没有办法从版本控制中删除文件而不从任何文件系统中删除它?
编辑:澄清,我希望。
我不认为 Git 提交可以记录诸如“停止跟踪此文件,但不要删除它”之类的意图。
制定这样的意图将需要在 Git 之外的任何存储库中进行干预,这些存储库合并(或变基到)删除文件的提交。
保存副本、应用删除、恢复
可能最简单的做法是告诉您的下游用户保存文件的副本,拉取您的删除,然后恢复文件。如果他们通过 rebase 拉动并对文件进行“携带”修改,他们将发生冲突。要解决此类冲突,请使用 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
来查找提交。
在评论中,您提到要“取消跟踪但保留”的文件是运行软件所需的某种配置文件(直接来自存储库)。
将文件保持为“默认”并手动/自动激活它
如果继续在存储库中维护配置文件的内容并非完全不可接受,您可以将跟踪文件从(例如)foo.conf
重命名为 foo.conf.default
,然后在应用重命名提交。或者,如果用户已经使用存储库的某些现有部分(例如,脚本或由存储库中的内容配置的其他程序(例如 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 manpage 中的“从上游 Rebase 恢复”部分)。配置文件所需的特殊处理只是从重写中恢复时必须执行的另一个步骤:
保存配置文件的副本。从重写中恢复。恢复配置文件。
忽略它以防止再次发生
无论您使用哪种方法,您都可能希望将配置文件名包含在存储库的 .gitignore
文件中,这样就不会有人无意中再次 git add foo.conf
(有可能,但需要 -f
/--force
)。如果您有多个配置文件,您可能会考虑将它们全部“移动”到一个目录中并忽略整个内容(“移动”是指更改程序期望找到其配置文件的位置,并获取用户(或启动/部署机制)将文件复制/移动到新位置;您显然不希望将文件 git mv 放入您将忽略的目录中)。
本周我意外提交时遇到了同样的问题,然后尝试从共享存储库中删除构建文件,并且:
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 的评论,这仅适用于本地,如果其他用户不这样做,该文件仍处于版本控制之下。接受的答案提供了更完整/正确的方法来处理这个问题。如果使用此方法,链接中还有一些注释:
显然,有很多注意事项与此有关。如果你直接 git add 文件,它将被添加到索引中。合并带有此标志的提交将导致合并正常失败,因此您可以手动处理它。
要从索引中删除文件,请使用:
git reset mylife
这不应影响您的本地副本或其他任何人的副本。
reset
仅当文件不在当前 HEAD 提交中时才从索引中删除该文件,否则它只是将索引版本恢复为当前 HEAD 版本。
git rm --cached remove_file 添加文件到 gitignore git add .gitignore git commit -m "Excluding" 玩得开心 ;)
执行 git rm --cached
命令后,尝试将 myfile
添加到 .gitignore
文件(如果不存在则创建一个)。这应该告诉 git 忽略 myfile
。
.gitignore
文件是版本化的,因此您需要提交它并将其推送到远程存储库。
我的解决方案是提取另一个工作副本,然后执行以下操作:
git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1
它说获取最新评论中的所有文件路径,并从 HEAD 的父级中检出它们。任务完成。
上述解决方案适用于大多数情况。但是,如果您还需要删除该文件的所有痕迹(即密码等敏感数据),您还需要将其从整个提交历史记录中删除,因为仍然可以从那里检索该文件。
这是一个解决方案,它从您的整个提交历史记录中删除文件的所有痕迹,就好像它从未存在一样,但仍将文件保留在您的系统上。
https://help.github.com/articles/remove-sensitive-data/
如果您在本地 git 存储库中,则实际上可以跳到第 3 步,并且不需要执行空运行。就我而言,我只需要步骤 3 和 6,因为我已经创建了 .gitignore 文件,并且位于我想要处理的存储库中。
要查看您的更改,您可能需要转到存储库的 GitHub 根目录并刷新页面。然后浏览链接以找到曾经拥有该文件的旧提交,以查看它现在已被删除。对我来说,简单地刷新旧的提交页面并没有显示更改。
起初它看起来很吓人,但实际上,它很容易,而且像一个魅力! :-)
--{,no-}assume-unchanged
的效果纯粹是本地的:它的状态不直接记录在提交中。它可以帮助防止存储库提交对文件的新更改,但不会将其从版本控制中删除。如果您可以为所有相关的、相关的、非裸存储库设置它,那么它可能会对您的情况有所帮助,但它不是您可以直接推+拉/变基到其他相关的、非- 裸存储库(尤其是您无法控制的存储库,根据原始提问者对问题的澄清评论:请参阅“人民系统”/“外国系统”)。I do not think a Git commit can record an intention like “stop tracking this file, but do not delete it”.
- 现在可以使用git rm --cached foo.conf