从Git历史记录中删除文件而不删除该文件

时间:2015-10-25 18:12:57

标签: git

我使用了GitHub的instructions for scrubbing a file from the commit history,但它从我的系统中删除了有问题的文件。这对我来说是令人惊讶的,因为git rm --cached命令本身应该保持文件本身不受影响。但是,在该页面上的工作示例中也可以看到此行为:尝试在大ls命令之前和之后运行git filter-branch ...

我正在使用Git 2.6.1。

如何在没有删除文件本身的情况下从提交历史中删除文件?显然我可以做一个备份(我在我的情况下做了),但这是一个解决方法,而不是解决方案。

2 个答案:

答案 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:

我可以使用8ef0c30HEAD@{1}(即HEAD之前的位置)或original/refs/remotes/origin/masteroriginal/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