撤消通过合并请求合并?


159

有人接受了他们不应该提出的请求。现在,我们已经合并了许多损坏的代码。如何撤消请求请求?我只是打算在合并之前将更改还原到提交,但是我注意到它已合并为一堆提交。因此,从合并之前的几天开始,此人已经提交了所有这些提交。您如何撤消此操作?


7
尽管已接受答案的建议,但如果回购与其他任何人共享,请不要强行推送到存储库。您冒着破坏他人完成的工作的风险,并且GitHub可能继续显示该合并请求为合并请求。此问题的另一个答案说明了撤消拉取请求的更安全方法。
alxndr 2014年

2
注意:至少现在(2014年6月),GitHub在其Pull Request Web GUI中建议使用“还原”按钮。请在下面
VonC

1
还原按钮的问题在于它会创建一个新的提交,作为对拉取请求的反向操作,这意味着,如果您最终想要合并这些更改,则使用“还原”按钮会使难度变得更大。
FluffySamurai

Answers:


159

尽管我可以逐步分解此问题,但对这个问题有一个更好的答案

您将需要像这样获取和签出最新的上游更改,例如:

git fetch upstream
git checkout upstream/master -b revert/john/foo_and_bar

查看提交日志,您应该找到类似以下内容:

commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Merge: 9271e6e a507888
Author: Tim Tom <tim@tom.com>
Date:   Mon Apr 29 06:12:38 2013 -0700

    Merge pull request #123 from john/foo_and_bar

    Add foo and bar

commit a507888e9fcc9e08b658c0b25414d1aeb1eef45e
Author: John Doe <john@doe.com>
Date:   Mon Apr 29 12:13:29 2013 +0000

    Add bar

commit 470ee0f407198057d5cb1d6427bb8371eab6157e
Author: John Doe <john@doe.com>
Date:   Mon Apr 29 10:29:10 2013 +0000

    Add foo

现在,您希望还原整个拉取请求,并具有稍后还原的能力。为此,您将需要获取合并提交的ID 。

在上面的示例中,合并提交是最上面的一个,其中显示“合并的拉取请求#123 ...”

执行此操作以还原两个更改(“ Add bar”“ Add foo”),最终将在一次提交中还原整个拉取请求,以后可以撤消此请求并保持更改历史记录的清洁:

git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269

6
这应该是正确的答案。有一个在混帐复归手册页更多细节从git的邮件列表的引用在这里kernel.org/pub/software/scm/git/docs/howto/...
贾斯汀Hamade

2
为什么git checkout upstream/master -b revert/john/foo_and_bar呢?它到底是做什么的?
Magne 2014年

4
@Magne-您正在创建一个新分支来进行还原,然后您可以选择合并分支的位置。基本上,您只是可以更好地控制分支的操作​​。就我而言,我从这个“固定”分支提交了一个新的请求请求,其中包含将其还原回我们的开发分支,这意味着如果需要的话,我的新请求请求也可以被还原。这样做是为了发布,我们决定发布重新安排的功能的初稿。没有不好的代码,只是不打算在这个版本中使用。
Daniel Nalbach

3
我在这方面学到了很难的教训。我们将一个功能推入了我们的开发分支,但意识到存在数据问题,并在开发时直接将其还原。后来,当问题解决后,我们希望在推送之前将更新的开发功能添加回该分支,以测试它们与此功能的兼容性,因此我将开发合并到功能分支。这还应用了还原提交,该提交取消了对功能分支所做的所有更改。> <
格雷格,

86

查看您的提交图(使用gitk或类似程序)。您将看到来自pull请求的提交,还将看到您自己的提交和一个合并提交(如果不是快速转发合并)。您只需要在合并之前找到您自己的最后一次提交,然后将分支重置为此提交即可。

(如果您有分支的引用日志,则在合并之前查找提交应该更加容易。)


(在评论中获取更多信息后进行编辑:)

好吧,让我们看一下图:

屏幕截图1

我认为最后一次(最右边)的提交是您通过pull request进行的错误合并,它合并了此处看到的蓝线。您的最后一个提交将是黑线之前的提交,此处用红色标记:

在此处输入图片说明

重置为该提交,就可以了。

这意味着,在您的本地工作副本中执行此操作(确保没有更多未提交的内容(例如,通过git stash)):

git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk 

现在,确认您确实在我在此处标记的提交上,并且在其祖先中将看不到任何被拉出的东西。

git push -f origin master

(如果您的github遥控器已命名origin-否则更改名称)。

现在,一切也应该在github上看起来正确。提交仍将在您的存储库中,但任何分支都无法访问,因此不应在此造成任何伤害。(当然,它们仍将保留在RogerPaladin的存储库中。)

(也许有一种Github特定于Web的方式可以完成相同的操作,但是我对Github及其拉取请求管理系统不太熟悉。)

请注意,如果其他任何人可能已经用错误的提交拉动了您的主服务器,那么他们将遇到与您当前遇到的问题相同的问题,并且无法真正做出贡献。重置为新的主版本之前。

如果很可能发生了这种情况,或者您只是想避免任何问题,请使用git revert命令而不是git reset来通过新的提交还原更改,而不是将其设置回旧的。(有些人认为您永远都不要对已发布的分支机构进行重置。)有关如何执行此操作的信息,请参见此问题的其他答案。

为将来:

如果只需要RogerPaladin分支的一些提交,请考虑使用cherry-pick而不是merge。或与RogerPaladin交流以将其移至单独的分支并发送新的拉取请求。


但是在合并和他的第一次提交之间有很多提交。因此,就像我们有合并提交一样,我们自己进行提交,然后由他进行另一次提交。看起来好像合并了他的旧作品。
威尔

是的,它将合并在所有合并提交的祖先(而不是已经提交的祖先)中。这不应该妨碍您进行重置-如果您之后没有进行任何基准调整,提交将不会被自己重新排序。
圣保罗Ebermann

1
是的,现在看起来不错(除了奇怪的合并本身 -但这可能是网络图软件中的一个小故障)。:-)很高兴能为您提供帮助。
圣保罗Ebermann

6
我认为,如果有人撤消了错误的提交,然后他们随后发送包含相同的错误提交的请求,则可能会出现问题,因此他们会偷偷溜进回购协议。创建一个新的提交来逆转错误的提交会更安全吗?这样,如果错误的提交已被拉到其他分支/分支,它们将被另一个拉到其他分支/分支的有效删除?我并不是说这是事实,我认为这可能是对的,与OP处于同一位置,花了一个小时左右的时间来考虑我的选择。
Myles McDonnell

4
@我会建议不接受这个答案。这对于尚未推送的代码很好(在这种情况下,是一个更相关的SO问题,但对于公开共享的代码,执行git命令重写历史记录(在这种情况下,reset --hard强制推送是这是非常糟糕的做法),以下@errordeveloper的答案显示了一种无需任何历史重写或强行推动的方式
asmeurer

34

如果拉是他做的最后一件事,那

git reset --hard HEAD~1

3
请谨慎执行此说明,它实际上使我倒退了2个步骤,而不是一个。
szeitlin '16

1
@szeitlin怎么可能会使您退回两步,而不是一步?我知道这则评论是4年前发布的,但我很好奇是否有人知道答案可能会如何发生。这对我来说很重要。谢谢。
Haradzieniec

我现在不记得了,但是我想如果在尝试重设时进行新的提交会发生这种情况吗?如果您担心它,我只会用一个虚拟仓库进行测试。
szeitlin

这对我来说效果很好。它删除了最近合并的拉取请求。之后git reset --hard HEAD~1,我用来git push origin -f更新远程存储库。但是要小心,在执行此操作之前要小心。
Denis Oluka

24

从2014年6月24日开始,您可以尝试轻松取消PR(请参阅“ 还原拉取请求 ”),方法是:

介绍还原按钮

您可以通过单击还原轻松地在GitHub上还原拉取请求:

https://camo.githubusercontent.com/0d3350caf2bb1cba53123ffeafc00ca702b1b164/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656d702de6c6ec3e6e6e6e6e2e3d

系统将提示您使用还原的更改创建新的请求请求:

https://camo.githubusercontent.com/973efae3cc2764fc1353885a6a45b9a518d9b78b/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f686ddfdfdfdfdfdfdfdfdfd

尽管该还原是否使用-m(还有还原合并),仍然有待测试。

但是Adil H Raza在评论中添加了内容(2019年12月):

这是预期的行为,它创建了一个新分支,您可以从该新分支到您的创建PR master
将来,您将来可以通过这种方式取消还原,这是最安全的选择,而不是直接更改master


警告Korayem指出在评论中说:

还原后,假设您在Git分支上做了一些进一步的更改,并从相同的源/目标分支创建了一个新的PR。
您会发现PR仅显示新的更改,而恢复之前没有任何变化

Korayem向我们介绍了“ Github:还原(git cherry-pickgit rebase)后忽略的更改 ”的更多信息。


我试过了,它创建了一个新分支,而不是撤消master上的PR?
Грозный

奇怪。您能否提出一个新问题来说明这种行为?
VonC

这是预期的行为,它创建了一个新分支,您可以从该新分支到您的主节点创建PR。将来,您将来可以通过这种方式取消还原,这是最安全的选择,而不是直接更改您的母版。
阿迪尔·拉扎

1
@ AdilH.Raza谢谢。我已将您的评论包含在答案中,以提高知名度。
VonC

1
@VonC十指交叉,这将使全球的开发人员免于过多的痛苦和时间浪费
Korayem

8

要撤消您不想删除的带有提交的github pull请求,您必须运行:

git reset --hard --merge <commit hash>

提交哈希是合并合并请求之前的提交。这将从拉取请求中删除所有提交,而不会影响历史记录中的任何提交。

找到它的一个好方法是转到现在关闭的拉取请求并找到以下字段:

拉取请求图像 拉取请求图像

运行后git reset,请运行:

git push origin --force <branch name>

这应该在拉取请求之前将分支还原回去,而不会影响分支中的任何提交,而分支中的任何提交都会插入到拉取请求之间的提交历史中。

编辑:

如果要单击拉取请求上的还原按钮,则会在分支上创建一个额外的提交。它不会取消提交或取消合并。这意味着,如果要单击还原按钮,则无法打开新的拉取请求以重新添加所有此代码。


无需任何疯狂的恢复或采摘就可以使事情
整顿的

谢谢!那是我打算做的事情,但是大约要花200次来挑选樱桃。
FluffySamurai

1

我一直在使用这个地方,谢谢。

我正在搜索如何撤消请求请求,并到达了这里。

我正要回到git reset --hard“很久以前”,然后快速返回到执行拉取请求之前的位置。

除了看这里,我还问了我的同事他会做什么,他通常会有一个很好的答案:使用上面第一个答案中的示例输出:

git reset --hard 9271e6e

与Git中的大多数事情一样,如果您以某种不容易的方式进行操作,则可能是错误的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.