1

I know there is a lot of information about undoing a merge in git, but I can't seem to find any concensus on how to do this in my specific situation.

Someone essentially merged our develop branch in to our master branch via a pull request in bitbucket. This just happened today, so it's the last thing that was done on the master branch (we don't have to worry about other commits on top of the merge commit).

Note: We host bitbucket ourselves, so we have an older version of bitbucket. There is no revert pull request option.

From what I've read, there is essentially two ways of handling this in git:

  1. git reset --hard *<SHA of commit before the merge>*

    • This will remove the merge commit as if it never happened.
    • Everywhere I read that "it's bad practice to rewrite history" or "never do this on a publicly shared repo" but they never really explain why not to do it. This seems like it will fix the problem, and it won't become a problem 6 months from now when we actually do want to redo this merge from develop to master
    • If this is the best way to do it, and we do it, what happens to the pull request in bitbucket? That pull request still exists in bitbucket, but we are removing the merge commit it created, so will that mess up bitbucket in any way?
  2. git revert -m 1 *<SHA of the merge commit>*

    • This will create a new commit that undoes the changes that were done by the merge
    • This would be fine, except we do intend to merge develop into master at a later date (the next release), and from what I've read, we would have to remember to revert our revert commit before doing this, because otherwise when we merge develop into master, the changes that we revert today won't be included. I really don't want to have this become a problem 6 months from now, when no one remembers this revert.

TL;DR: I'm hesitant on doing git revert because of the issues it could cause 6 months from now when we do want to do this merge again. I'm also hesitant on doing git reset because everyone seems to warn against doing it, and it could cause issues with the pull request on bitbucket.

wired_in
  • 2,593
  • 3
  • 25
  • 32

2 Answers2

2

You can do either. There is really no decisive technical reasons which would dictate you what to do.

  1. in exceptional cases it's ok to update non-forward. Explain to each, ask team who has pulled the erroneous master, help them to recover.

  2. You can forward the development branch to revert commit, then revert the revert, thus returning to its content.

PS for case 2:

For original case

* 73d5415 (HEAD -> master) master3
| * e660100 (development) development3
| * 0356d3a development2
| * 6cefad0 development1
|/  
* 209d967 master2
* dc25505 master1

You merged the development into master, and reverted it.

* 7a4f94a (HEAD -> master) Revert "Merge branch 'development'"
*   75e1e34 Merge branch 'development'
|\  
| * e660100 (development) development3
| * 0356d3a development2
| * 6cefad0 development1
* | 73d5415 master3
|/  
* 209d967 master2
* dc25505 master1

Now to fix it, you shoud do

$ git checkout development
$ git merge --ff-only master
$ git revert 7a4f94a (the "Revert" commit)

Result:

e7b511a (HEAD -> development) Revert "Revert "Merge branch 'development'""
* 7a4f94a (master) Revert "Merge branch 'development'"
*   75e1e34 Merge branch 'development'
|\  
| * e660100 development3
| * 0356d3a development2
| * 6cefad0 development1
* | 73d5415 master3
|/  
* 209d967 master2
* dc25505 master1

e7b511a Contains all your development which used to be not in master and can be merged to master later. There is downside though that all of it is represented as single commit, so if you mean to blame somethig it will require one more call in e660100.

max630
  • 8,762
  • 3
  • 30
  • 55
  • Can you elaborate on number 2? I don't follow. Especially with your use of "forward". Are you saying there is a way to change `develop` such that it will take into account the revert when we do the merge from `develop` to `master` in 6 months? – wired_in Sep 08 '17 at 18:55
  • added example with graphs – max630 Sep 08 '17 at 22:47
  • Wow thanks for the detailed answer. I'll definitely mark this as the accepted answer, but one more thing.We can't do a fast-forward merge from master to development because there have been other commits on development since we did the revert in master. Does that change anything? Can I still accomplish this by doing a merge commit on develop instead of a fast-forward merge? – wired_in Sep 09 '17 at 21:40
  • 1
    you could do non-fastforward merge as well, but if the newer commits require the development code there would be conflict – max630 Sep 10 '17 at 04:43
  • Worked perfectly, thanks again! I accepted your answer. – wired_in Sep 15 '17 at 16:42
0

[As I am yet to get enough reputations, I can not put comments on your question, so adding my comments as answer]

The only way I know to revert to old hash of master (without showing merge commit and then reversal of the commit) is to force-push. Refer git force-push for examples and options.

This is a debatable answer, as there are many with opinion against it. But as you are using bitbucket, the force-push can be controlled, i.e. enable it for your operation and disable the force-push for your master.

Note: bitbucket latest plugins like rebase and squash use --force-with-lease.

RuSh
  • 159
  • 4
  • Thanks for the answer, however I think you are misunderstanding what I'm asking. I know I'll have to do a force push to master if I use `git reset --hard`, however my question is whether it would be best to do it that way, or should I do a `git revert` instead, which would not rewrite history and thus wouldn't cause a force push. Reread my question to understand why I'm hesitant on using both approaches. – wired_in Sep 09 '17 at 21:43
  • `git reset` and `force push` would rewrite the history so people suggest not to use it, but if you have control (bitbucket provides that) then it can be used in such situations. As I see none of the suggestions are giving exact answer you are looking for, so may I suggest you to create a dummy repository with dummy files and branches? Reproduce the situation on it and see which solution would work for you. By this way, you can safely try out many things without disturbing your master. – RuSh Sep 10 '17 at 05:27