假设您的 git 历史记录如下所示:
1 2 3 4 5
1-5 是单独的修订版。您需要在保留 1、2、4 和 5 的同时删除 3。如何做到这一点?
当要删除的修订后有数百个修订时,有没有一种有效的方法?
假设您的 git 历史记录如下所示:
1 2 3 4 5
1-5 是单独的修订版。您需要在保留 1、2、4 和 5 的同时删除 3。如何做到这一点?
当要删除的修订后有数百个修订时,有没有一种有效的方法?
根据这个评论(我检查了这是真的),rado 的答案非常接近,但让 git 处于分离的头部状态。相反,删除HEAD
并使用它<commit-id>
从您所在的分支中删除:
git rebase --onto <commit-id>^ <commit-id>
这是一种以非交互方式删除特定的方法<commit-id>
,只知道<commit-id>
您要删除的内容:
git rebase --onto <commit-id>^ <commit-id> HEAD
要将版本 3 和 4 合并为一个版本,您可以使用 git rebase。如果要删除修订版 3 中的更改,则需要在交互式变基模式下使用编辑命令。如果要将更改合并到一个修订版中,请使用 squash。
我已经成功地使用了这种 squash 技术,但以前从未需要删除修订。“拆分提交”下的 git-rebase 文档有望为您提供足够的想法来弄清楚。(或者其他人可能知道)。
从git 文档:
从您希望按原样保留的最旧提交开始:
git rebase -i <after-this-commit>
一个编辑器会被你当前分支中的所有提交触发(忽略合并提交),这些提交在给定提交之后。您可以将此列表中的提交重新排序为您心中的内容,您可以删除它们。该列表或多或少看起来像这样:
选择 deadbee 本次提交的单行 选择 fa1afe1 下一次提交的单行 ...在线描述纯粹是为了您的乐趣;git-rebase 不会查看它们,而是查看提交名称(在此示例中为“deadbee”和“fa1afe1”),因此不要删除或编辑名称。
通过用命令“edit”替换命令“pick”,您可以告诉 git-rebase 在应用该提交后停止,以便您可以编辑文件和/或提交消息,修改提交,并继续变基。
如果要将两个或多个提交合并为一个,请将命令“pick”替换为“squash”以进行第二次和后续提交。如果提交有不同的作者,它会将压扁的提交归于第一次提交的作者。
如前所述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 中所做的更改,您可能需要使用 git revert。
Git revert 只是创建一个新的修订版本,其中的更改会撤消您正在恢复的修订版本中的所有更改。
这意味着您保留了有关不需要的提交和删除这些更改的提交的信息。
如果有人可能同时从您的存储库中拉出,这可能会更加友好,因为恢复基本上只是一个标准提交。
到目前为止,所有答案都没有解决尾随问题:
当要删除的修订后有数百个修订时,有没有一种有效的方法?
步骤如下,但作为参考,让我们假设以下历史:
[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
分支指向你之前所在的位置,以防你想调和。
您希望如何安排其他人转移到您的新历史记录取决于您。您需要熟悉stash
、reset --hard
和cherry-pick
。您可以删除base
,remove-me
和save
分支
我也遇到了类似的情况。使用下面的命令使用交互式变基,并在选择时删除第 3 次提交。
git rebase -i remote/branch
所以这是我面临的场景,以及我是如何解决的。
[branch-a]
[Hundreds of commits] -> [R] -> [I]
这R
是我需要删除的提交,并且I
是之后的单个提交R
我做了一个还原提交并将它们压在一起
git revert [commit id of R]
git rebase -i HEAD~3
在交互式 rebase squash 期间,最后 2 次提交。
rado 和 kareem 的答案对我没有任何作用(只有消息“当前分支是最新的。”出现)。这可能是因为 '^' 符号在 Windows 控制台中不起作用。但是,根据此评论,将 '^' 替换为 '~1' 可以解决问题。
git rebase --onto <commit-id>^ <commit-id>