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
--ontooption be useful?
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!!