简体   繁体   English

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

[英]Remove a file from Git history without deleting the file

I used GitHub's instructions for scrubbing a file from the commit history , but it deleted the file in question from my system. 我使用GitHub的指令从提交历史记录中清除文件,但它从我的系统中删除了有问题的文件。 This was surprising to me because the git rm --cached command itself should leave the file itself untouched. 这对我来说是令人惊讶的,因为git rm --cached命令本身应该保持文件本身不受影响。 But this behavior can also be seen in the worked example on that page: try running ls before and after the big git filter-branch ... command. 但是这个行为也可以在该页面上的工作示例中看到:尝试在big git filter-branch ...命令之前和之后运行ls

I'm using Git 2.6.1. 我正在使用Git 2.6.1。

How can I delete a file from the commit history without deleting the file itself? 如何在删除文件本身的情况下从提交历史记录中删除文件? Obviously I could just make a backup (which I did in my case), but that's a workaround and not a solution. 显然我可以做一个备份(我在我的情况下做了),但这是一个解决方法而不是解决方案。

When git-filter-branch is done it checks out the new branch head. git-filter-branch完成时,它会检出新的分支头。 This will update your working directory to a clean state. 这会将您的工作目录更新为干净状态。 The file you wanted obliterated from history has been obliterated. 你想要从历史中删除的文件已被删除。 Backing up beforehand is the solution. 预先备份是解决方案。

If you forgot to back it up, you can still get it back! 如果你忘记备份它,你仍然可以取回它! Git takes a long time to throw things out, your original commits are still in there. Git需要花费很长时间才能解决问题,你的原始提交仍在那里。 After git-filter-branch there will be a branch called original/refs/heads/master (if you filtered master) which contains the original commits. git-filter-branch之后会有一个名为original/refs/heads/master的分支(如果你过滤了master),它包含原始提交。 You can recover the file from there. 您可以从那里恢复文件。

In general, you can recover filters and rebases using git reflog . 通常,您可以使用git reflog恢复过滤器和rebase。 It's a log of every time HEAD changes (ie. you checkout or rebase or merge or filter or...). 这是每次HEAD更改时的日志(即您结帐或变基或合并或过滤或......)。 For example, after doing the Github filter example, git reflog is... 例如,在执行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:

I can use 8ef0c30 or HEAD@{1} (ie. the previous location of HEAD ) or original/refs/remotes/origin/master or original/refs/heads/master to get back to where things were before the filter ran. 我可以使用8ef0c30HEAD@{1} (即HEAD的先前位置)或original/refs/remotes/origin/masteroriginal/refs/heads/master来回到过滤器运行之前的位置。

First of all: 首先:

(It needs to be said.) (需要说的是。)

When using git filter-branch you are doing history rewriting in an automated manner according to your own (maybe buggy) specification. 使用git filter-branch您将根据自己的(可能是错误的)规范以自动方式进行历史记录重写 Thus you should make a backup of your repo before doing that, anyway , or perform the operation on a fresh separate clone of your repo. 因此, 无论如何您应该在执行此操作之前备份您的仓库 ,或者在您的仓库的新单独克隆上执行操作。

Why the file also vanishes from your working copy 为什么文件也会从您的工作副本中消失

git filter-branch applies the specified command to each applicable commit. git filter-branch将指定的命令应用于每个适用的提交。 However, it doesn't check out those commits in your working copy to do that. 但是,它不会检查您的工作副本中的那些提交来执行此操作。 Instead, it checks them out into .git-rewrite/ by default, or to the directory you gave with the -d option. 相反,它默认.git-rewrite/它们检入.git-rewrite/ ,或者使用-d选项.git-rewrite/它们检出。 (See git filter-branch documentation, option -d <directory> .) (参见git filter-branch文档,选项-d <directory> 。)

After having rewritten the applicable commits, Git checks out the resulting new branch. 在重写了适用的提交之后,Git会检查生成的新分支。 As this is a switch from a branch with the file (the pre-rewrite version of that branch) to one without the file (the post-rewrite version of that branch), the file is deleted from your working copy, too. 由于这是从具有文件的分支(该分支的预重写版本)切换到没有文件的分支(该分支的重写后版本),因此该文件也从您的工作副本中删除。

How you can preserve the file 如何保存文件

Well, make a backup. 好吧,做个备份。

(Note that a tag or branch won't be an adequate backup if you're rewriting all branches and all tags as is done in the example at https://help.github.com/articles/remove-sensitive-data/ .) (请注意,如果您正在重写所有分支和所有标记,则标记或分支将不是足够的备份,如https://help.github.com/articles/remove-sensitive-data/中的示例所示。 )

How you can retrieve the file if you haven't done that 如果你没有这样做,你如何检索文件

See Schwern's answer . 请参阅Schwern的回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM