1

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

所以这里是问题:

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

git rm files

然后提交。我尝试再次推送,然后才意识到删除文件不会将其从 git 历史记录中删除。// 所以现在,从上次完成的推送中,我有 2 个提交:1 个我添加文件的地方,1 个我删除的地方一些.csv。

我希望您能帮助我删除最后 2 次提交。这可行吗?谢谢

4

3 回答 3

2

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

假设您想从所有提交中删除一个文件(包含机密信息或侵犯版权):

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

(请参阅文档页面上的详细信息,我没有在这里复制粘贴整个内容)

于 2018-09-25T17:08:53.547 回答
1

...我想...删除最后 2 个提交。这可行吗?

你不能完全删除提交,但你可以很容易地告诉 Git忘记它们。

最后,它的工作方式非常简单。我们首先注意到每个提交都会保存一个快照,并且还存储其父提交的哈希 ID(以及您的提交日志消息和您作为作者的姓名等)。这形成了一个向后指向的提交链。

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

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

请注意,在这种情况下,分支名称存储链中最后一次提交master的哈希 ID 。(当某物存储提交的哈希 ID 时,我们说该物指向该提交,因此是箭头。名称指向,指向,依此类推。)masterHHG

Git 找到这些提交的方式是读取Hout of的哈希 ID master,它定位 commit H,然后读取 commitH并显示它。然后,在 readH之后,Git 的哈希 ID 为 commit G,因此 Git 可以读取G并显示它,依此类推。

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

  • 写出快照;
  • 写出作者和日志信息等;
  • 点返回到当前提交;
  • 最后也是最重要的,将提交的哈希 ID 写入分支名称。

所以如果我们有:

...--F--G--H

我们补充说--I

...--F--G--H--I

然后 Git 更改了名称 master以存储 commit 的哈希 ID I。最终我们有:

...--F--G--H--I--J   <-- master

如果我们做了几个不需要的提交,我们可以告诉 Git:重新设置名称master以指向 commitH而不是 commit J 有几种方法可以做到这一点,但在这种情况下,第一种方法是git reset --hard(虽然我们已经master检查过,并确保您没有担心丢失的任何东西,因为git reset --hard告诉 Git 将所有东西都扔掉):

git checkout master
git reset --hard HEAD~2

~2后缀告诉 Git 倒数两个步骤——从技术上讲,两个第一个父步骤,当我们的链中有一些合并提交时,这很重要,但在这里,我们不这样做,所以没关系。如果master当前指向J,则 Git 倒计时两次:JI,然后IH。然后 Git 将我们的工作替换为来自 commit 的内容H 并使名称master, 指向H而不是J:

             I--J
            /
...--F--G--H   <-- master

现在J很难找到,它似乎已被删除。

这样做的缺点是,如果我们让我们的 Git 告诉其他 Git:在这里,复制提交IJ其他 Git 有这两个提交,并且即使在我们的 Git 忘记它们之后,也会将它们重新引入我们自己的 Git . 但是,如果我们从未在其他任何地方成功发送过这两个提交,那么我们就是唯一拥有它们的人,所以如果我们忘记它们,它们就如同消失了一样好。

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

于 2018-09-25T17:55:47.813 回答
1

如果我们谈论的是 biiiig 历史,正如我们所建议的那样,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

这应该足够了。

于 2018-09-25T17:52:44.113 回答