Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rebase reverted merged branch

Tags:

git

merge

Background: I recently merged a rather large topic branch into master. A couple of days later I discovered this topic branch contained bugs. So I git revert -m 1 <merge-commit>ed it.

Problem: Now I'd like to check out the topic branch and rebase it against current master so that I can 1) fix the bugs and 2) (again) merge the fixed up topic branch with master. Creating the new branch, fixedtopic is the easy part, but every time I do

git checkout fixedtopic
git rebase master

git decides that it's not willing to replay the old commits since they are already merged into master. Instead it simply does a fast-forward rebase.

Question: How can force replay of the commits onto fixedtopic using rebase? Can I? I'd rather not use cherry-pick since it's a bit more cumbersome.

Additional:

  • git reseting the merge commit it not an option, since I have pushed the master upstream.
  • I'd rather not create a new branch off of master and revert my revert. The reason for this is that I'd like to rewrite some of the topic branch's history using interactive rebase.
  • Here's a github gist of the scenario: https://gist.github.com/JensRantil/6352495 Note that I'd like e8df5ec and ee16464 applied onto master (or branch based on master).
like image 841
Ztyx Avatar asked Aug 27 '13 10:08

Ztyx


People also ask

Can you rebase a merged branch?

By default, the git pull command performs a merge, but you can force it to integrate the remote branch with a rebase by passing it the --rebase option.

How do I revert a branch after merge?

To undo a git merge, you need to find the commit ID of your last commit. Then, you need to use the git reset command to reset your repository to its state in that commit. There is no “git revert merge” command.

Can a merge be reverted?

You can use the Git reset command to undo a merge. Firstly, you need to check for the commit hash (or id) so you can use it to go back to the previous commit. To check for the hash, run git log or git reflog . git reflog is a better option because things are more readable with it.


5 Answers

The documentation (git help rebase) suggests that "git rebase --force-rebase" does just this -- but (Git 1.9.1) it doesn't. The documentation also suggests that "git rebase -i --no-ff" is equivalent to that command -- but it isn't: it does work.

Having cloned your gist, the commands:

  git checkout topic
  git rebase -i --no-ff --onto master 7b3af topic

produce the desired result, with new versions of the "third" and "fourth" commits on top of master, and topic pointing at the new version of "fourth". In the second command, the SHA 7b3af is the "second" commit, the point where topic was branched from.

like image 126
Peter Hartley Avatar answered Oct 01 '22 07:10

Peter Hartley


One way to achieve this is to interactively rebase the topic branch and reword the first commit after branching out of master (e.g. git rebase -i HEAD~10 if you have 10 commits in the branch). This will rewrite sha's of all the commits inside the topic branch. Therefore you will be able to rebase the usual way with git rebase master.

like image 41
jurglic Avatar answered Oct 01 '22 06:10

jurglic


With git 2.22, the solution suggested by jurglic does not seem to work anymore.

Let's start with the status, to make sure that we are talking about the same thing:

P---o---o---M---o---o---o---o---o---W---o---o---master
 \         /     \                /
  A---B---C       D (revert A-B-C)

I had created a dev branch with A-B-C commits and it was merged in M, but immediately we noticed there was an error so it was reverted in W. I would like to rebase A-B-C on master and fix the issue before merging it again.

Here is what I did:

git checkout C          (detached HEAD) 
git checkout -b redo
git rebase -i master

But at this point, git offered me only the following:

noop

# Rebase A..C onto X (1 command)

This meant that it figured out that I was trying to reapply the exact same commits and they had already been merged.

To workaround this problem, jurglic had suggested to modify A's the commit message but it seems that git 2.22 is clever enough to figure it out and was still offering me the exact same noop. I tried other solutions, using --force-rebase and/or --no-ff, but I was all the time back to noop.

Finally, I used an easy short-cut by entering manually in the rebase -i selection editor and I replaced noop with:

pick A
pick B
pick C

or, if you want to save even more keystrokes:

p A
p B
p C

This worked finally like a charm.

like image 42
Louis Caron Avatar answered Oct 01 '22 06:10

Louis Caron


You need to use --onto to prevent Git form trying to determine the appropriate unmerged commits on its own.

E.g. (with topic branch checked out):

git rebase --onto master <id-of-branch-point>

For <id-of-branch-point> you want the git merge-base of your topic branch and the commit on master before the merge that you reverted.

Edit

Re-reading your situation again, it might be a better if you fast-forward the topic branch to the point where you reverted the merge, then revert the reversion and fix the topic branch from that point. This way you won't get a repetition of all the commits in the original topic branch but with new ids in the final history of master. Whatever you do, you're going to end up with a history involving "do, undo, redo", but this way might be considered a cleaner history.

like image 32
CB Bailey Avatar answered Oct 01 '22 08:10

CB Bailey


What seems to work best is to check out a new branch, and then re-instate the previous working branch by reverting revert.

Everything else that I've tried is overly complicated and/or doesn't work.

like image 26
Steve Jorgensen Avatar answered Oct 01 '22 08:10

Steve Jorgensen