Search code examples
gitgit-mergegit-pushgit-pullgit-reset

Reverting a git pull that's already been pushed


I'm not sure if this is a duplicate or not as it's kind of a one off scenario:

I have a "beta" branch, and started a new "refactor" branch.

  1. I did a bunch of code in "refactor" branch.
  2. I pulled latest changes from beta into refactor (git checkout refactor && git pull origin beta)
  3. My changes were ready, so I checked out beta, and pulled changes from refactor into beta. (git checkout beta && git pull origin refactor)
  4. Realized my beta branch wasn't up to date, so had to do a git pull to pull latest into beta.
  5. Now that beta branch was up to date, did another git pull origin refactor to ensure the latest was there (got an auto-commit message that refactor was being merged into beta).
  6. I pushed my code :(

So now I'm realizing the two things I did wrong:

  1. In step 3, I should have done a git pull first so that I had the latest changesets in beta
  2. In step 3 also, I realized i should have called git merge refactor instead of git pull origin refactor (don't ask me why I did this, it's Monday and I just wanted to get my awesome refactor code into beta to start testing). I now realize if I had done both of these things, none of the later steps would have been needed.

So my question is this: technically, all the code is there and looks fine, but the network graph on github looks super funky, and I don't have one clean "merge" commit that I can easily roll back to if my merged branch needs to be reverted, instead beta just now has all of my individual commits from the refactor branch. Is there an easy way I can roll back my stupified merge and do it the cleaner way?

I have tried doing git checkout beta && git reset --hard beta@{"1 hour ago"} , but the problem is that gets me to the outdated local version of beta instead of what should have been the latest version before I issued the merge when I should have done the git pull first. I feel like there should be a way to do like git reset --hard origin/beta@{"1 hour ago"} to reset to the remote beta branch @ 1 hour ago, and then do the git merge refactor? Would I just be able to push those changes and be sure that the remote commits were overwritten?

Thanks for any help in advance! I'm hesitant about doing anything with "git reset" as the refactor is pretty major, and there are a lot of pending changes in beta that I didn't do, so I'm more worried about screwing up a reset and losing code than I am worried about having to manually revert commits from the refactor branch that were pulled in.


Solution

  • Did you do a force push of beta branch?

    If so I assume you don't need to synchronize this one with other developers, so it is ok to force push again. In that case I suggest:

    • do an interactive rebase for example for last 10 commits "git rebase -i HEAD~10"
    • remove commits that got merge from refactor branch and make sure the beta is clean and updated latest version of the branch
    • force push it
    • go to refactor branch and rebase it on beta (git checkout refactor && git rebase beta)
    • go to beta and merge refactor in without ff (git checkout beta && git merge --no-ff refactor)
    • this will give you nice and readable history graph

    If you can't do a force push, then you can complicate the graph even more. You could do a revert commit for every commit in beta that got pulled out of refactor. This way you will get beta branch into clean and updated state. After that, just repeat the last 3 steps of the upper recipe. You will get nice graph out of that, but history before this one stays.