3

I've merged a side branch (feature/b) into develop, I got merge conflicts and I made an incorrect decision on how to resolve them. I then made a manual commit to fix some other problems. More commits came in to feature/b and I then merged these too I then realised my mistake and reverted the last merge.

Everything got pushed to the remote, and has been pulled by the team.

Things are now messy. I need to get develop stable again, but also be able to have another go at resolving the conflicts from the original merge.

What's my best option to solve this?

  • revert all three steps? If I understand things correctly this doesn't get me the second shot at fixing the original conflicts?
  • reset the head? effectively destroying history? does that affect history to other branches?
  • give up and create e.g. develop2 branch before I went wrong?

I've read this closely related answer, but I'm looking for more guidance : How to revert a merge commit that's already pushed to remote branch?

Nimantha
  • 6,405
  • 6
  • 28
  • 69
timB33
  • 1,977
  • 16
  • 33

3 Answers3

4

This sounds like a messy situation indeed.

My approach would be your last suggestion: give up and create a new dev branch before things went wrong. On that branch, you can redo the merge that was not done correctly and then cherry pick all the good commits that were done after the incorrect merge. Push that and ask the team to work on the new dev branch.

This solution has the advantage that if anyone has unpushed commits on the bad dev branch, they can also privately cherry-pick them onto the good one.

joanis
  • 10,635
  • 14
  • 30
  • 40
2

Whatever you do, do not reset and push forced develop because it's shared with other dev and it will get messier.

You can revert but as you saw, be aware that previously merged commits will be ignored in future merge (as history didn't change). I would recreate the feature branch as if it was a new one.

You can easily do this with a rebase by specifying from which commit to start the rebase, which is what is explained in the link you provided.

Let's say we're in this situation

 /B-C\(feature/1)
A-----D-E(develop)

where A is develop before the merge and the origin of the branch, C is feature/1 branch at the moment of the merge, D the merge commit, E the attempt to fix it.

First revert D and E, as D is a merge commit, you'll have to specify which parent to revert to using -m, it should be 1 but check (git revert D -m 1). Then rebase branch feature/1 on on commit A (origin of the branch)

git checkout feature/1
git rebase --no-ff A (no-ff to force rebase)

Then you'll end up like this :

 /B-C\
A-----D-E-F(develop)
 \B'-C'(feature/1)

where F is the commit for the reverts and B' and C' newly created commits.

And you can merge feature/1 as if it's a new branch.

Matt
  • 3,422
  • 1
  • 23
  • 28
1

This answer assumes that you current feature/b branch looks something like this:

feature/b:  .. M -- A -- B -- C

Here M is the merge commit you did not want, and then commits A through C came in from other developers, who had pulled the branch, and then pushed. We may try using git revert with a range:

git revert -m 1 HEAD~3^..HEAD

The syntax HEAD~3^..HEAD means to revert commits from and including three before the HEAD commit up to an including the HEAD commit. The -m 1 option tells Git to follow the first parent of the branch, which typically would be the branch on the remote (the branch source of the merge would be -m 2).

Note that it is necessary to git revert here because you have already published this branch. Things like hard reset and other history-altering choices would not be ideal here.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360