从整个git历史记录中删除文件

时间:2018-09-25 17:02:37

标签: git commit git-rm

我知道这个问题已经问过了,但是在每个答案中,我发现情况与我的情况略有不同,我不知道如何适应它。

这就是问题所在:

我克隆了一个存储库,并添加了一个要在其中使用的文件夹。在此文件夹中,我添加了.csv文件和使用csv文件的.py文件。 我试图推动这一点,但意识到只要2个csv文件非常大,它就花费了很长时间。所以我

git rm files

,然后提交。我试图再次推送,然后才意识到删除文件不会将其从git历史记录中删除。 因此,现在,从最后一次完成的推送中,我进行了2次提交:1添加文件,1删除一些.csv。

我希望您能帮助您删除最近的两次提交。那可行吗? 谢谢

3 个答案:

答案 0 :(得分:2)

我发现git filter-branch文档中的第一个示例非常适合您的上下文。看看(source):

  

假设您要从所有提交中删除文件(包含机密信息或侵犯版权的内容):

git filter-branch --tree-filter 'rm filename' HEAD
# and see also the variant further in the example description
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

(请参阅文档页面上的详细信息,我避免在此处复制粘贴整个内容)

答案 1 :(得分:1)

如我们所建议,如果我们谈论的是历史,可以使用

filter-branch。如果我们只讨论一些修订,则可以通过修改添加文件和樱桃选择的修订来实现(删除文件)。

一个例子.....说我在master〜2上添加了文件a.txt。我不再想要历史了。

git checkout master~2 git rm --cached a.txt git commit --amend --no-edit git cherry-pick master~2..master git branch -f master # point master in this revision git checkout master

那应该足够了。

答案 2 :(得分:1)

  

...我想...删除最后2次提交。那可行吗?

您不能完全删除 提交,但是您可以轻松地告诉Git 忘记

最后,此方法非常简单。我们首先注意到每个提交都保存一个快照,并存储其 parent 提交的哈希ID(以及您的提交日志消息和您的作者姓名,依此类推)。这形成了一个向后的提交链。

如果让单个大写字母代表提交哈希ID,我们可以绘制此链:

... <-F  <-G  <-H   <--master

请注意,在这种情况下,分支名称 master last 提交的哈希ID存储在链中。 (当某个东西存储了提交的哈希ID时,我们说这个东西指向提交,因此是箭头。名称master指向H,{{1 }}指向H,依此类推。)

Git查找这些提交的方式是从G中读取H的哈希ID,这将找到提交master,然后读取提交H并显示它。然后,在读取H之后,Git具有提交H的哈希ID,因此Git可以读取G并显示它,依此类推。

当我们进行新的提交时,Git实际上是通过以下方式实现的:

  • 写出快照;
  • 写出作者和日志消息等;
  • 具有 new 指向 current 提交;
  • 最后也是最重要的一点是,将 new 提交的哈希ID写入分支名称。

所以,如果我们有:

G

,我们添加了...--F--G--H

--I

然后Git更改了名称 ...--F--G--H--I ,以存储提交master的哈希ID。最终,我们有了:

I

如果我们进行了多次不需要的提交,我们可以告诉Git:重新设置名称...--F--G--H--I--J <-- master 指向提交master而不是提交H有几种方法可以做到这一点,但是在这种情况下,第一个可以实现的方法是J(当我们检出git reset --hard时,请确保您没有担心的任何事情)失败,因为master告诉Git将一切丢掉):

git reset --hard

后缀git checkout master git reset --hard HEAD~2 告诉Git倒退两个步骤-从技术上讲,两个 first parent 步骤,当链中有一些合并提交时,这很重要,但是在这里,我们不这样做所以没关系。如果~2当前指向master,则Git会倒数两次:JJ,然后II。然后,Git用提交H 中的内容替换我们的工作,并且使名称H指向master而不是H

J

现在 I--J / ...--F--G--H <-- master 很难找到,它似乎被删除。

这样做的缺点是,如果我们让Git告诉其他Git:在这里,复制JI的提交副本,两次提交,即使我们的Git忘记了它们,它们也会重新引入它们到我们自己的Git中。但是,如果我们从未成功将这两个提交发送到其他任何地方,那么我们是唯一拥有它们的人,因此,如果我们忘记了它们,那么它们就像消失了一样好

((如果我们已经推入它们,我们可以拥有我们的Git,他们的 Git,以及其他所有拾起它们的Git 从那时起,全部忘记了它们,然后 then 消失了,但这显然很快就变得很困难。)