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

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

How do you remove a specific revision in the git history?

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

1
2
3
4

1–5是单独的修订。 您需要删除3,同时仍然保留1、2、4和5。如何完成?

当要删除的修订有数百个时,有没有一种有效的方法?


这是一种非交互方式删除特定的方法,仅知道您要删除的

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

根据这个评论(我检查了这是真的),rado的答案非常接近,但是git处于分离状态。而是删除HEAD并使用它从您所在的分支中删除

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


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

我已经成功使用了这种壁球技巧,但是之前从未需要删除修订版。希望"分裂提交"下的git-rebase文档应该给您足够的想法来解决它。 (或者其他人可能知道)。

从git文档:

Start it with the oldest commit you want to retain as-is:

git rebase -i

将使用当前分支中的所有提交(忽略合并提交)来激发编辑器,这些提交将在给定提交之后进行。您可以按照自己的意愿对列表中的提交进行重新排序,也可以将其删除。该列表大致如下所示:

1
2
3
pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

单行描述纯粹是为了您的愉悦; git-rebase不会查看它们,而是查看提交名称(在此示例中为" deadbee"和" fa1afe1"),因此请勿删除或编辑名称。

通过将命令" pick"替换为命令" edit",您可以告诉git-rebase在应用该提交后停止,以便您可以编辑文件和/或提交消息,修改提交,并继续进行基础调整。

如果要将两个或多个提交折叠为一个,则将" pick"命令替换为" squash",以进行第二个及后续提交。如果提交的作者不同,则将压缩的提交归因于第一个提交的作者。


如前所述,git-rebase(1)是您的朋友。假设提交在您的master分支中,您将执行以下操作:

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

之前:

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

后:

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

从git-rebase(1):

A range of commits could also be
removed with rebase. If we have the
following situation:

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

then the command

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

would result in the removal of
commits F and G:

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

This is useful if F and G were flawed in some
way, or should not be part of topicA.
Note that the argument to --onto and
the parameter can be any
valid commit-ish.


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

Git revert只需创建具有更改的新修订,即可撤消您要还原的修订中的所有更改。

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

如果这同时完全有可能有人从您的存储库中拉出了,这可能会更加友好,因为还原基本上只是一个标准的提交。


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

Is there an efficient method when there are hundreds of revisions
after the one to be deleted?

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

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

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

R:
提交将被删除

B:
就在要删除的提交之前提交(基本)

由于存在"数百次修订"约束,因此我假设以下前提条件:

  • 有一些令人尴尬的承诺,您希望从未存在过
  • 有零个后续提交实际上取决于该尴尬的提交(还原时为零冲突)
  • 您不在乎您会被列为数百个中间提交的"提交者"("作者"将被保留)
  • 您从未共享过存储库

    • 或者您实际上对曾经克隆过历史的所有人都具有足够的影响力,以说服他们使用您的新历史
    • 而且你不在乎重写历史
  • 这是一组限制性很强的约束,但是有一个有趣的答案实际上可以在这种极端情况下起作用。

    步骤如下:

  • git branch base B
  • git branch remove-me R
  • git branch save
  • git rebase --preserve-merges --onto base remove-me
  • 如果确实没有冲突,则不应再有任何干扰。如果存在冲突,您可以解决它们并rebase --continue或决定忍受尴尬和rebase --abort

    现在您应该位于master上,其中不再包含提交R。 save分支指向您之前的位置,以防您需要调和。

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


    我也遇到了类似的情况。使用下面的命令使用交互式变基,然后选择并删除第3个提交。

    1
    git rebase -i remote/branch

    所以这是我面临的场景以及如何解决它。

    1
    2
    3
    [branch-a]

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

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

    我进行了一次提交提交并将其压缩在一起

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

    在交互式变基壁球期间,最后2次提交。


    rado和kareem的答案对我没有任何帮助(仅显示消息"当前分支是最新的。")。可能是因为" ^"符号在Windows控制台中不起作用。但是,根据此注释,用'?1'替换'^'可解决此问题。

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

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

    首先在cmd以下运行

    1
    rm -rf .git

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

    1
    2
    3
    git init                                                                          
    git add .                                                  
    git commit -m"first commit"

    -推送到github远程仓库

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


    推荐阅读