我使用了GitHub的instructions for scrubbing a file from the commit history,但它从我的系统中删除了有问题的文件。这对我来说是令人惊讶的,因为git rm --cached
命令本身应该保持文件本身不受影响。但是,在该页面上的工作示例中也可以看到此行为:尝试在大ls
命令之前和之后运行git filter-branch ...
。
我正在使用Git 2.6.1。
如何在没有删除文件本身的情况下从提交历史中删除文件?显然我可以做一个备份(我在我的情况下做了),但这是一个解决方法,而不是解决方案。
答案 0 :(得分:4)
当git-filter-branch
完成时,它会检出新的分支头。这会将您的工作目录更新为干净状态。你想要从历史中删除的文件已被删除。预先备份是解决方案。
如果您忘记备份,您仍然可以取回它! Git需要花费很长时间才能解决问题,你的原始提交仍在那里。在git-filter-branch
之后,将有一个名为original/refs/heads/master
的分支(如果您过滤了主数据库),其中包含原始提交。您可以从那里恢复文件。
通常,您可以使用git reflog
恢复过滤器和rebase。它是每次HEAD
更改的日志(即您签出或重新绑定或合并或过滤或...)。例如,在执行Github过滤器示例后,git reflog
是......
abaabaf (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: filter-branch: rewrite
8ef0c30 (refs/original/refs/remotes/origin/master, refs/original/refs/heads/master) HEAD@{1}: clone:
我可以使用8ef0c30
或HEAD@{1}
(即HEAD
之前的位置)或original/refs/remotes/origin/master
或original/refs/heads/master
来回到之前的状态过滤器跑了。
答案 1 :(得分:4)
(需要说的是。)
使用git filter-branch
时,您根据自己的(可能是错误的)规范以自动方式执行历史记录重写。因此,你应该备份你的回购,然后无论如何,或者在回购的新单独克隆上执行操作。
git filter-branch
将指定的命令应用于每个适用的提交。但是,它不会检查您的工作副本中的那些提交来执行此操作。相反,默认情况下会将它们检出.git-rewrite/
,或者使用-d
选项将其检出。 (请参阅git filter-branch
文档,选项 -d< directory> 。)
在重写了适用的提交后,Git会检出生成的新分支。由于这是从具有文件(该分支的预重写版本)的分支切换到没有文件的分支(该分支的重写后版本),因此该文件也从您的工作副本中删除。
好吧,做个备份。
(请注意,如果您正在重写所有分支和所有标记,则标记或分支将不是足够的备份,如https://help.github.com/articles/remove-sensitive-data/中的示例所示。)
请参阅Schwern's answer。