January 18, 2019
There are lots of commands in git and you can often achieve your goal in several different ways. I usually manage to get my stuff done with just few cmds like rebase, reset, cherry-pick. But sometimes I felt I was doing it ineffectively. Like for example squashing all commits into a single one so that it will be easier to rebase afterward.
Even though I knew that rebasing with the
--onto option would be useful, I never took the time to man it… until recently. I guess now is a good time to write something about it.
🌳 I assume in this post that you have basic knowledge about git, and that you are familiar with its index, working tree as well as commands like reset and cherry-pick
Here are some use-cases:
Basically it all comes down to this: apply a range of commits somewhere else
Let’s begin with a little reminder about how rebase works in its simplest form. From the man (unix) we get:
git rebase upstream [branch]
I am gonna give some examples and intentionally avoid any short-hand way at first.
When you run the command
git rebase master topic then:
git reset --hard masterexcept that commits X, Y, Z are put aside for later use. Basically all commits that are in topic but not in master (
Step 2 may fail applying the commits. Don’t worry, be happy, you can either resolve the conflict by running
git rebase --continue or get back to the state you left before the rebase with
git rebase --abort
Note If you already are on the topic branch (HEAD → topic) then you can omit the branch arg and just type
git rebase master (step 0 is skipped) This is a common short-hand.
The man tells us:
git rebase --onto newbase upstream [branch]
The only difference is in step 1: git hard resets to newbase instead of upstream. Step 2 remains the same, commits upstream..branch are applied.
You have created a branch topicB from topicA but it was a “mistake”. The work on topicB is totally unrelated to topicA and thus doesn’t depend on it.
So naturally, you need to rectify this unfortunate mistake to make topicB fork from master.
To do so you can run:
git rebase --onto master topicA topicB
As seen previously, step 1 is hard resetting to master, step 2 is applying commits
I told you in the intro that we could also remove a range of commits by using this option. Well lets say you have a branch like the one below and want to get rid of commits F and G.
You can run:
git rebase --onto E G I
Step 1 is a hard reset to E and step 2 is picking
(as a reminder G is excluded: this is how
.. works in git)
F and G are removed.
-i option lets you visualize commits that are concerned by the rebase and interact with them. You can squash, delete, rename, edit… basically playing with the past!!