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

180*_*ION 211 git

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

1 2 3 4 5

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

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

rad*_*ado 122

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

git rebase --onto <commit-id>^ <commit-id> HEAD
Run Code Online (Sandbox Code Playgroud)

  • 请参阅@ kareem的建议,在他的答案中省略`HEAD`,以避免分离头. (11认同)
  • @hopia它表示指定提交的(第一个)父级.请参阅"git help revision" (3认同)
  • 也为我工作。顺便说一句,^运算符是做什么的?这是否意味着在指定的提交之后进行下一个提交? (2认同)

小智 120

根据这个评论(我检查过这是真的),rado的答案非常接近,但是让git处于一个独立的头状态.相反,删除HEAD并使用它<commit-id>从您所在的分支中删除:

git rebase --onto <commit-id>^ <commit-id>
Run Code Online (Sandbox Code Playgroud)

  • 您能否在答案中解释一下魔法命令的作用?即每个参数代表什么? (3认同)
  • 出于某种原因,当我运行它时没有任何反应.然而,将`^`改为`~1`使它工作. (2认同)

gar*_*thm 76

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

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

git文档:

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

git rebase -i <after-this-commit>

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

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

在线描述纯粹是为了您的乐趣; git-rebase不会查看它们,而是查看提交名称(本例中为"deadbee"和"fa1afe1"),因此不要删除或编辑名称.

通过使用命令"edit"替换命令"pick",您可以告诉git-rebase在应用该提交后停止,以便您可以编辑文件和/或提交消息,修改提交并继续重新定位.

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

  • -1这个问题很明确,但这个答案并不那么明确.作者没有说明确切的解决方案是什么. (40认同)

rve*_*ica 76

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

git rebase --onto master~3 master~2 master
Run Code Online (Sandbox Code Playgroud)

之前:

1---2---3---4---5  master
Run Code Online (Sandbox Code Playgroud)

后:

1---2---4'---5' master
Run Code Online (Sandbox Code Playgroud)

来自git-rebase(1):

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

E---F---G---H---I---J  topicA
Run Code Online (Sandbox Code Playgroud)

那么命令

git rebase --onto topicA~5 topicA~3 topicA
Run Code Online (Sandbox Code Playgroud)

会导致删除提交F和G:

E---H'---I'---J'  topicA
Run Code Online (Sandbox Code Playgroud)

如果F和G在某种程度上存在缺陷,或者不应该成为topicA的一部分,那么这很有用.请注意,--onto和参数的参数可以是任何有效的commit-ish.

  • 不应该是` - 大师~3大师~1`? (3认同)
  • 如果你只想删除最后一次提交,那就是--onto master~1 master (3认同)

Spo*_*ser 22

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

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

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

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

  • 不幸的是,对我来说不是一个好的解决方案,因为有人意外地将100MB的废话交给了回购,炸毁了大小并使网络界面变得迟钝. (4认同)

jds*_*ion 18

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

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

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

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]
Run Code Online (Sandbox Code Playgroud)

C:提交后删除提交(干净)

R:要删除的提交

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

由于"数百个修订"约束,我假设以下前提条件:

  1. 你希望从未存在过一些令人尴尬的承诺
  2. 还有ZERO后续提交,实际上取决于那个令人尴尬的提交(恢复时的零冲突)
  3. 你不在乎你会被列为数百个干预提交的"提交者"('作者'将被保留)
  4. 你从未共享过存储库
    • 或者你实际上对所有曾经克隆历史的人有足够的影响力来说服他们使用你的新历史
    • 不关心有关改写历史

这是一组相当严格的约束,但有一个有趣的答案实际上适用于这个角落的情况.

以下是步骤:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

如果确实没有冲突,那么这应该不再进一步中断.如果有冲突,你可以解决它们,rebase --continue或者决定只是忍受尴尬和尴尬rebase --abort.

现在你应该对master不再有提交- [R在里面.该save分支点到你之前在哪里,如果你想调和.

您希望如何安排其他人转移到您的新历史记录取决于您.您将需要与相识stash,reset --hardcherry-pick.你可以删除base,remove-mesave分支机构