在从事开源项目时,我遇到了以下 git 问题。我做了一些更改,并发送了拉取请求。 PR一开始就被接受了。然而,我的更改结果出现了一些微妙的错误,维护者再次恢复了我的提交,要求我在解决问题后发送新的拉取请求。然而,中间发生了很多其他提交,所以我需要更新我的拉取请求。不幸的是,我无法让 git 在
master
的最新状态之上重新设置或挑选我的旧 PR。
让我用一个例子来澄清一下。比如说,我最初的拉取请求已提交
A
和 B
并被接受。然后,几次提交后,我的 PR 被恢复(R
),然后又发生了一些提交。历史是这样的:
...--A---B--...--R--...--o master
现在,我想将其转换为以下形式,以便在
master
的最新状态之上完善我的拉取请求:
...--A---B--...--R--...--o master
\
A---B newPR
但是,我未能通过
rebase
和cherry-pick
实现这一目标。问题似乎是,git 认为 A
和 B
已经是 master
的一部分,因为它们已经在历史中了。因此,它不会在 master
之上应用这些更改。
如何强制 git 执行此操作?
除了cherry-pick选项之外,rebase现在还有一个
--force-rebase
选项来生成新的提交,以便它会忽略之前恢复的合并。
另请参阅:revert-a-faulty-merge How-To、
git rebase --no-ff
,以及完整的 git rebase
文档。
已编辑
git checkout master
git checkout -b redo
git cherry-pick Aref
git cherry-pick Bref
... do fixes and commits
git merge master
之前
* e553928d35646512f640b0f0ca208f6729884993 D
* 5157867afdbdcf4300f7b722e3816e294e0f2ae4 C
* caa01fd5378f87b67811212aa4325963fab72905 Revert "A"
* 8603f6b1231dbefa4911699cb59fa81f1a20e432 Revert "B"
* d4c38c2c63ab0b4be00480bf9c9542ffc66dcb5f B
* f2f6e0a0b7a804a4a8075839d7b73b37b747a7b3 A
* 59597e64b49b234b45a94a86d950f0811a19cdfe root commit
之后
* e6a314b66d8be8a85abd6becd53e0d2c7a6332a5 E
* d7d91af4225d5ba7d783303e73bcac1b5ba02a91 B
* 381b95bea7f87662f72a1da67bd70cdfc497be47 A
* e553928d35646512f640b0f0ca208f6729884993 D
* 5157867afdbdcf4300f7b722e3816e294e0f2ae4 C
* caa01fd5378f87b67811212aa4325963fab72905 Revert "A"
* 8603f6b1231dbefa4911699cb59fa81f1a20e432 Revert "B"
* d4c38c2c63ab0b4be00480bf9c9542ffc66dcb5f B
* f2f6e0a0b7a804a4a8075839d7b73b37b747a7b3 A
* 59597e64b49b234b45a94a86d950f0811a19cdfe root commit
在本地为我工作
$ git checkout master
Switched to branch 'master'
$ ls
A B C D E
用你的例子
...Z---A---B--...--R--...--o master
并使用 Git 2.34.0+
您可以使用这些命令来解决这个问题
git rebase -f Z
git rebase --reapply-cherry-picks o
第一个命令基本上是创建一个新分支并挑选所有分支提交的操作
然后第二个命令将将该分支重新设置为新的基础(在本示例中为 o)。因为新分支中的提交是经过挑选的,所以我们需要选项 --reapply-cherry-picks 来告诉 git 应用这些挑选,从而忽略恢复的提交