你如何删除git历史中的特定版本?

假设你的git历史logging如下所示:

1 2 3 4 5

1-5是单独的修订。 你需要删除3,同时保持1,2,4和5.这个怎么做?

有一个有效的方法,当有一个被删除的数以百计的修改后?

要将版本3和版本4合并成一个版本,可以使用git rebase。 如果要删除修订版本3中的更改,则需要在交互式底线模式下使用编辑命令。 如果您想要将更改合并到一个修订版本中,请使用压扁。

我已经成功地使用了这种压扁技术,但从来没有需要删除修订。 “拆分提交”下的git-rebase文档应该有希望给你足够的想法。 (或者别人可能知道)。

从git文档 :

用你想要保留的最旧的提交开始它:

git rebase -i <after-this-commit>

一个编辑器将会触发当前分支中的所有提交(忽略合并提交),这是在给定提交之后发生的。 您可以将此列表中的提交重新sorting,以便将其删除。 列表看起来或多或less是这样的:

 挑选死虫这个提交的oneline
selectfa1afe1下一个提交的oneline
 ... 

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

通过使用命令“edit”replace命令“pick”,可以告诉git-rebase在应用该提交后停止,以便可以编辑文件和/或提交消息,修改提交并继续重新绑定。

如果要将两个或多个提交合并为一个,请将“pick”命令replace为“squash”作为第二个提交。 如果提交具有不同的作者,它将把压扁的提交归因于第一次提交的作者。

这是一种非交互式地删除特定的<commit-id> ,只知道你想删除的<commit-id>

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

根据这个评论 (我检查了这是真的),拉多的答案是非常接近,但离开了头部状态的混帐。 相反,删除HEAD并使用它从您所在的分支中删除<commit-id>

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

如前所述, 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的一部分,这是非常有用的。 请注意,参数 – 参数和参数可以是任何有效的提交ish。

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

Git还原只是简单地创build一个新的修订版本,其中的更改会撤销正在还原的修订版本中的所有更改。

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

这可能是更友好的,如果有可能的话,这个人同时从你的仓库中取出,因为回复基本上只是一个标准的提交。

迄今为止所有的答案都没有解决尾随的问题:

有一个有效的方法,当有一个被删除的数以百计的修改后?

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

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

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

R :要删除的提交

B :提交之前提交被删除(基地)

由于“数百修订”的限制,我假定以下前提条件:

  1. 有一些你不希望存在的尴尬承诺
  2. 有零后续的提交,实际上取决于那个尴尬承诺(回复零冲突)
  3. 你不在乎你将被列为数百个干预提交的“提交者”(“作者”将被保留)
  4. 你从来没有共享知识库
    • 或者你实际上对所有曾经克隆过历史的人都有足够的影响力,让他们说服他们使用你的新历史
    • 你不在乎 重写历史

这是一个相当严格的约束条件,但是有一个有趣的答案,实际上在这个angular落案例中起作用。

这里是步骤:

  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分支指向您以前的位置,以防您想调和。

你想如何安排其他人转移到你的新历史取决于你。 你将需要熟悉stashreset --hardcherry-pick 。 你可以删除baseremove-me ,并save分支机构

所以这是我面对的情况,以及我如何解决它。

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

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

我做了一个恢复承诺,把他们压在一起

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

在交互式重新压缩最后2次提交。

我也遇到了类似的情况。 使用下面的命令使用交互式底图,select时,放弃第三次提交。

 git rebase -i remote/branch 

rado和kareem的答案对我没有帮助(只显示“Current branch is up to date”的消息)。 可能发生这种情况是因为'^'符号在Windows控制台中不起作用。 但是,根据这个评论,用'〜'代替'^'解决了这个问题。

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