如何删除git历史记录中的特定修订版?

时间:2008-08-31 22:51:21

标签: git

假设您的git历史记录如下:

1 2 3 4 5

1-5是单独的修订。你需要删除3,同时仍然保持1,2,4和5.如何做到这一点?

在要删除的修订版之后有数百个修订版时,是否有一种有效的方法?

10 个答案:

答案 0 :(得分:118)

以下是一种非交互式删除特定<commit-id>的方法,只知道您要删除的<commit-id>

git rebase --onto <commit-id>^ <commit-id> HEAD

答案 1 :(得分:114)

Per this comment(我检查过这是真的),rado的答案非常接近,但是让git处于一个独立的头状态。相反,请移除HEAD并使用此功能从您所在的分支中移除<commit-id>

git rebase --onto <commit-id>^ <commit-id>

答案 2 :(得分:74)

如前所述git-rebase(1)是你的朋友。假设提交在你的master分支中,你会这样做:

git rebase --onto master~3 master~2 master

在:

1---2---3---4---5  master

后:

1---2---4'---5' master

来自git-rebase(1):

  

一系列提交也可以   用rebase删除。如果我们有   以下情况:

E---F---G---H---I---J  topicA
     

然后命令

git rebase --onto topicA~5 topicA~3 topicA
     

会导致删除   提交F和G:

E---H'---I'---J'  topicA
     

如果F和G在某些方面存在缺陷,这将非常有用   方式,或不应成为topicA的一部分。   请注意--onto和。的参数   参数可以是任意的   有效的commit-ish。

答案 3 :(得分:72)

要将版本3和版本4合并为单个版本,可以使用git rebase。如果要删除修订版3中的更改,则需要在交互式rebase模式下使用edit命令。如果要将更改组合到单个修订中,请使用squash。

我已成功使用此壁球技术,但以前从未需要删除修订版。 “Splitting commits”下的git-rebase文档应该会给你足够的想法来解决它。 (或其他人可能知道)。

来自git documentation

使用您希望保留的最旧提交启动它:

git rebase -i <after-this-commit>

将在当前分支中的所有提交(忽略合并提交)启动编辑器,这些提交在给定的提交之后。您可以将此列表中的提交重新排序到您的内容,然后您可以删除它们。该列表看起来或多或少像这样:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

oneline描述纯粹是为了您的乐趣; git-rebase不会查看它们,而是查看提交名称(本例中为“deadbee”和“fa1afe1”),所以不要删除或编辑名称。

通过使用命令“edit”替换命令“pick”,可以告诉git-rebase在应用该提交后停止,以便您可以编辑文件和/或提交消息,修改提交,然后继续垫底。

如果要将两个或多个提交折叠成一个,请将命令“pick”替换为“squash”以进行第二次和后续提交。如果提交有不同的作者,它会将压缩的提交归因于第一次提交的作者。

答案 4 :(得分:22)

如果您只想删除修订版3中所做的更改,则可能需要使用git revert。

Git revert只是创建一个新版本,其中包含撤消修订版本中所有更改的更改。

这意味着,您保留有关不需要的提交和删除这些更改的提交的信息。

如果有人在同一时间从你的存储库中撤出,这可能会更加友好,因为恢复基本上只是一个标准的提交。

答案 5 :(得分:15)

到目前为止,所有答案都没有解决拖尾问题:

  

当有数百个修订时,是否有一种有效的方法   在要删除之后?

以下步骤,但作为参考,我们假设以下历史记录:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

C 的:   提交之后提交要删除(干净)

- [R :   要删除的提交

:   提交之前提交要删除(基础)

由于&#34;数百次修订&#34;约束,我假设以下前提条件:

  1. 你希望从未存在过一些令人尴尬的提议
  2. 有零随后的提交实际上依赖于那个令人尴尬的提交(恢复时的零冲突)
  3. 您并不关心自己是否会被列为“提交者”。数以百计的介入提交(&#39;作者将被保留)
  4. 您从未共享过存储库
    • 或者你实际上对所有曾经克隆过历史记录的人有足够的影响力来说服他们使用你的新历史
    • don't care关于rewriting history
  5. 这是一组相当严格的约束,但有一个有趣的答案实际上适用于这个角落。

    以下是步骤:

    1. git branch base B
    2. git branch remove-me R
    3. git branch save
    4. git rebase --preserve-merges --onto base remove-me
    5. 如果确实没有冲突,则应该不再进行中断。如果存在冲突,您可以解决这些冲突并rebase --continue或决定只是忍受尴尬和rebase --abort

      现在你应该在master上不再提交 R save分支指向您之前的位置,以防您想要协调。

      您希望如何安排其他人转移到您的新历史记录取决于您。您需要熟悉stashreset --hardcherry-pick。您可以删除baseremove-mesave分支

答案 6 :(得分:2)

所以这是我遇到的情景,以及我是如何解决的。

[branch-a]

[Hundreds of commits] -> [R] -> [I]

此处R是我需要删除的提交,而IR之后的单个提交

我做了一个还原提交并将它们压在一起

git revert [commit id of R]
git rebase -i HEAD~3

在交互式rebase压缩期间,最后2次提交。

答案 7 :(得分:2)

我也陷入了类似的境地。使用以下命令使用交互式rebase,在选择时,删除第3次提交。

git rebase -i remote/branch

答案 8 :(得分:0)

rado和kareem的答案对我没有任何帮助(只有消息&#34;当前分支是最新的。&#34;出现)。可能会发生这种情况,因为&#39; ^&#39;符号在Windows控制台中不起作用。但是,根据this评论,替换&#39; ^&#39;通过&#39; ~1&#39;解决了这个问题。

git rebase --onto <commit-id>^ <commit-id>

答案 9 :(得分:-3)

要从git repo中删除旧的提交历史记录:

首先在cmd以下运行

rm -rf .git

-从当前版本重新创建仓库

git init                                                                           
git add .                                                  
git commit -m "first commit"

-推送到github远程仓库

git remote add origin git@github.com<your git mail>   
git push -u --force origin master