无法推送到 gerrit,因为先前的变更集已被放弃

Cannot push to gerrit as the previous changeset was abandoned

我本地工作树中过去的 3 次提交如下:

latest: my current changes
latest-1: my previous commit, that I pushed to gerrit and subsequently aborted
latest-2: an earlier commit by someone else

现在当我得到如下错误时:

git push origin HEAD:refs/for/dev
! [remote rejected] HEAD -> refs/for/dev (change https://git/1326970 closed)

1326970 是我放弃的 latest-1 提交的变更集。我如何也将它从我的本地工作树中删除?

当我做 git remote update && git rebase git 说 First, rewinding head to replay your work on top of it... 并且它应用两个提交 LATEST-1LATEST。我是否需要重置回之前的状态然后进行更改?

通常,要删除提交,请使用 git reset。在这种情况下,如果您想保留 latest 提交但删除 latest-1,这会稍微复杂一些,因为您不能只将分支设置回 X 提交。

请记住,Git 的数据结构的每个提交都指向其父提交,因此 latest 包含对 latest-1 的引用。我们需要做的是合成一个新的 latest 提交,不再包含您在 latest-1 中更改的内容,并将 latest-2 作为其父级存储。

这听起来很复杂,但幸运的是 Git 有一个强大的工具来进行历史修改,称为 interactive rebase,如下所示:

  1. 你运行git rebase -i latest-2("do horrible things to everything after latest-2").
  2. Git 启动一个列出您的提交的编辑器。删除行以删除提交,还有许多其他您可以做的事情,记录在 git rebase 的联机帮助页中,第 交互模式 .
  3. 部分
  4. 完成后,保存并退出,Git 将re-generate 根据您的订单提交。 (如果您改变主意,请在保存前清除编辑器内容,它将中止。)
    • 在每次提交期间 re-generated(latest,在您的情况下),可能会发生冲突(如果 latest "depend on" 中的更改 latest-1). Git 将向文件添加冲突标记并告诉您如何继续。

在合并提交时要小心。默认情况下,交互式变基会严重破坏它们。您可以使用 -p 选项告诉它不要这样做,但您会得到完全不同的代码路径,并且可能存在其他细微差别。


或者,对于这种特殊情况,这里有一个更快的选项:重置然后手动 re-apply 个人提交。

git reset --hard latest-2 # warning, destroys uncommitted changes
git cherry-pick latest # ID of latest (which is now gone but can still be referenced)