5

I would like to rebase to a specific commit that is not the HEAD of the other branch, but going backwards:

A --- B --- C          master
            \
             \-- D --- E   topic

to

A --- B --- C          master
      \
       \-- D --- E   topic

How do I achieve this in an elegant and general way?

By general I mean that the target commit (B) may not necessarily be the direct ancestor of HEAD (I might as well rebase to A or a previous commit) and that there may be many more than just two commits on topic branch. I might also want to rebase from B to A.

Krzysiek Karbowiak
  • 1,655
  • 1
  • 9
  • 17
  • I think `git rebase --onto B --root master` should work. (just use `--onto A --root B` when rebasing from B to A). – Joachim Sauer Nov 08 '19 at 09:11
  • Do what @JoachimSauer suggests, just make sure topic you're on the topic branch when you do it. – John Szakmeister Nov 08 '19 at 09:16
  • @JohnSzakmeister Or `git rebase master topic --onto B`. – alfunx Nov 08 '19 at 09:20
  • Loosely related to [this question](https://stackoverflow.com/questions/32315156/how-to-inject-a-commit-between-some-two-arbitrary-commits-in-the-past)? Might be. – Romain Valeri Nov 08 '19 at 09:26
  • @alfunx That'll work too... though I personally dislike it--I always feel like the arguments should be swapped--so I prefer the other version, since I can never quite remember the order from the top of my head. :-) – John Szakmeister Nov 08 '19 at 09:31
  • @JohnSzakmeister I just type the command assuming that I'm on the correct branch, then add the second argument later, in case I'm not. But I agree — it can be confusing. – alfunx Nov 08 '19 at 10:02

1 Answers1

7

Using git cherry-pick

git rebase is a git cherry-pick on steroids.

If you only have a few commits to move : you may use git cherry-pick to pick them one by one

# move back to B
git checkout B

# start a branch here, and use it as the active branch
git checkout -b wip

# cherry-pick the commits you want to have
git cherry-pick D
git cherry-pick E

# if all went well : move the 'topic' branch to the current branch :
git checkout topic
git reset --hard wip

# delete the temporary 'wip' branch
git branch -d wip

Using git rebase

As mentioned in the comments : git rebase can take extra options to move only a range of commits.

You can do the same as the above cherry-pick sequence using :

git rebase --onto B master topic

Extra note : git rebase -i

git rebase also has an --interactive|-i flag :

git rebase -i --onto B master topic

With the -i flag : before doing anything, git will open a text editor for you, where all the rebased commit will be listed.

This step has the obvious benefit of showing you what will be applied (before actually applying it), and also to describe more actions than just "picking that commit".

You can search the web for more complete tutorials on git rebase -i, here is one :
Git Interactive Rebase, Squash, Amend and Other Ways of Rewriting History (thoughtbot.com)

LeGEC
  • 46,477
  • 5
  • 57
  • 104