Undo a merge by pull request?
There is a better answer to this problem, though I could just break this down step-by-step.
You will need to fetch and checkout the latest upstream changes like so, e.g.:
git fetch upstream
git checkout upstream/master -b revert/john/foo_and_bar
Taking a look at the commit log, you should find something similar to this:
commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269 Merge: 9271e6e a507888 Author: Tim Tom <[email protected]> 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 <[email protected]> Date: Mon Apr 29 12:13:29 2013 +0000 Add bar commit 470ee0f407198057d5cb1d6427bb8371eab6157e Author: John Doe <[email protected]> Date: Mon Apr 29 10:29:10 2013 +0000 Add foo
Now you want to revert the entire pull request with the ability to unrevert later. To do so, you will need to take the ID of the merge commit.
In the above example the merge commit is the top one where it says "Merged pull request #123...".
Do this to revert the both changes ("Add bar" and "Add foo") and you will end up with in one commit reverting the entire pull request which you can unrevert later on and keep the history of changes clean:
git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Look at your commit graph (with gitk or a similar program). You will see commits from the pull request, and you will see your own commits, and a merge commit (if it was not a fast-forward merge). You just have to find the last of your own commits before the merge, and reset the branch to this commit.
(If you have the branch's reflog, it should be even easier to find the commit before the merge.)
(Edit after more information in comments:)
Okay, lets look at the graph:
I assume the last (rightmost) commit was your wrong merge by pull request, which merged the blue line seen here. Your last good commit would be the one before on the black line, here marked in red:
Reset to this commit, and you should be fine.
This means, in your local working copy do this (after making sure you have no more uncommitted stuff, for example by git stash):
git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk
Now confirm that you are really on the commit I marked there, and you will see none of the pulled stuff in its ancestry.
git push -f origin master
(if your github remote is named origin
- else change the name).
Now everything should look right on github, too. The commits will still be in your repository, but not reachable by any branch, thus should not do any harm there. (And they will be still on RogerPaladin's repository, of course.)
(There might be a Github specific web-only way of doing the same thing, but I'm not too familiar with Github and its pull request managing system.)
Note that if anyone else already might have pulled your master with the wrong commit, they then have the same problem as you currently have, and can't really contribute back. before resetting to your new master version.
If it is likely that this happened, or you simply want to avoid any problems, use the git revert
command instead of git reset
, to revert the changes with a new commit, instead of setting back to an older one. (Some people think you should never do reset with published branches.) See other answers to this question on how to do this.
For the future:
If you want only some of the commits of RogerPaladin's branch, consider using cherry-pick
instead of merge
. Or communicate to RogerPaladin to move them to a separate branch and send a new pull request.
If the pull was the last thing he did then
git reset --hard HEAD~1
Starting June 24th, 2014, you can try cancel a PR easily (See "Reverting a pull request") with:
Introducing the Revert Button
you can easily revert a pull request on GitHub by clicking Revert:
You'll be prompted to create a new pull request with the reverted changes:
It remains to be tested though if that revert uses -m
or not (for reverting merges as well)
But Adil H Raza adds in the comments (Dec. 2019):
That is the expected behavior, it created a new branch and you can create a PR from this new branch to your
master
.
This way in the future you can un-revert the revert if need be, it is safest option and not directly changing yourmaster
.
Warning: Korayem points out in the comments that:
After a revert, let's say you did some further changes on Git branch and created a new PR from same source/destination branch.
You will find the PR showing only new changes, but nothing of what was there before reverting.
Korayem refers us to "Github: Changes ignored after revert (git cherry-pick
, git rebase
)" for more.
To undo a github pull request with commits throughout that you do not want to delete, you have to run a:
git reset --hard --merge <commit hash>
with the commit hash being the commit PRIOR to merging the pull request. This will remove all commits from the pull request without influencing any commits within the history.
A good way to find this is to go to the now closed pull request and finding this field:
Pull Request Image
After you run the git reset
, run a:
git push origin --force <branch name>
This should revert the branch back before the pull request WITHOUT affecting any commits in the branch peppered into the commit history between commits from the pull request.
EDIT:
If you were to click the revert button on the pull request, this creates an additional commit on the branch. It DOES NOT uncommit or unmerge. This means that if you were to hit the revert button, you cannot open a new pull request to re-add all of this code.