Back to REBASE-ics

My favourite method of merging feature branches has to be "rebase and merge" (that's a "semi-linear merge" if you're using DevOps) - it allows us to avoid losing data while keeping the tree clean and tidy.

But what is a rebase and how do they work?

, by Joe Glombek

I've taken an example git repository so we can walk through how we'd do this with rebase and merge.

A git tree with three feature branches. The feature/another-talk branch is already merged, while two remain unmerged.

We can actually see the merge of the feature/another-talk branch is already complete since it's cleanly merged into main with no intermediate commits to main - there was no need to rebase and merge, so it's just the other two branches we need to worry about.

The "Write talk" commit cherry-picked onto a new branch off of main

Now, I've created a new branch from the latest main and faded out our existing feature/git-talk branch.

If you've ever done a cherry-pick before to move a commit from one branch to another, a rebase is like an extreme version of that! When told to rebase, git will cherry-pick each commit in a branch in turn and add it to a new branch at the point requested (in this case, a later version of the same main branch).

Here I've "cherry-picked" the "Write talk" commit and put it onto our new branch.

feature/git-talk branch fully rebased onto main

Then we repeat that for all the other commits needed (including "fix typos" in that other branch), adding them in order and fixing any merge conflicts that may come about for each one.

And that's actually the rebase out the way! We've "cherry picked" each commit and resolved any merges, but in a more automated way than actually doing loads of cherry-picks.

feature/git-talk branch fully rebased and merged

Now it's time to merge feature/git-talk into main.

That old branch doesn't need to be there anymore - it doesn't actually exist locally, so we can hide that.

feature/git-talk branch fully rebased and merged with the old un-rebased branch removed

And then all we have to do is rebase and merge our final branch, feature/another-talk.

Final rebased structure with branches making an uninterrupted 'D' shape against the main branch

To give us this!

Each feature makes a neat "D" shape with the main or develop branch, with no crossovers. As you can see, when compared to a traditional merge process shown below this method removes the muddle of crisscrossing merges, while maintaining the whole branch structure and all the detail in every commit.

Traditional merge method with crisscrossing merges

For more information on why I prefer this practice and other git tips, check out my "Why are you being such a git about it?" article on Skrift.