January 18, 2019

There are lots of commands in git and we can often achieve our goal in several different ways. I usually manage to get my stuff done with just few commands 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 is easier to rebase. Even though I heard that rebasing with the onto option could be useful, I never took the time to man it… until recently. So what are some use cases?

we want to cherry-pick multiples commits

we have created a branch from the wrong one

we want to delete a range of commits

Basically it all comes down to this: apply a range of commits elsewhere

Rebase

Let’s begin with a little reminder about how rebase works in its simplest form. The man gives us:

git rebase upstream [branch]

To illustrate this, let’s take an example. topic has forked master from B but in the meantime a new commit— C —has arrived on master. To bring topic up to date with master we can run:

git rebase master topic

Here is what happens:

Git performs a checkout topic The index and working tree are reset to master ( reset --hard master ) Commits in topic but not in master—namely X, Y, Z—are put aside for later use Those commits are applied one by one on master. This is like “cherry-picking” them.

Note If we already are on the topic branch (HEAD → topic) then we can omit the branch arg and just type git rebase master (step 0 is skipped) This is a common short-hand.

The --onto option

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.

This is particularly useful when we want to change the base branch.

Example

We 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. To fix this unfortunate mistake and make topicB fork from master, we can run:

git rebase --onto master topicA topicB

Step 1 is hard resetting to master, step 2 is applying commits topicA..topicB .

Removing some commits

I told you in the intro that we could also remove a range of commits by using this option. Well, lets say we have a branch like the one below and want to get rid of commits F and G.

Step 1 is a hard reset to E and step 2 is picking G..I (as a reminder G is excluded: this is how .. works in git) F and G are removed.

Let’s play with the past