I’m a big believer in keeping a clean commit history. This practice isn’t always necessary depending on the type of work being done, but I frequently reference old commits, so keeping the merge commits out of my history just helps me to get rid of the noise. This means, that I rebase my branches often which can cause an issue when branching off branches, as once a branch is merged into the main branch, you need to catch up your currently working branch some how.

So here’s the process I follow to make sure that all my branches stay up to date. Lets say I’m working on branch-B which is branched off branch-A which itself is branched off main.

Note: You can see a similar output to this by doing git log --pretty=oneline.

# branch-B commits
b-3
b-2
b-1
a-3 (branch-A)
a-2
a-1

# branch-A commits
a-3
a-2
a-1

Lets say branch-A gets merged to main via a merge commit. The merge commit squashes a-1,2,3 into a single commit and now main has all the changes on the remote origin. Now we’re left with branch-B which looks like:

b-3
b-2
b-1
a-3
a-2
a-1

The fix is really encapsulated into a single command, but before we do that we have to ensure our local main is up to date so it has those changes.

$ git checkout main
$ git pull

Now that the local version of main is up to date we can now rebase branch-B onto main from branch-A. The git command almost reflects that sentence perfectly.

$ git checkout branch-B
$ git rebase --onto main branch-A

What happens here is that branch-B upstream changes from branch-A to main but with gits knowledge of what happened to branch-A which in this case was a merge commit. This means, that the merge commit is honored, and only the commits from branch-B proper are re-applied. So after this the history of branch-B looks like:

# branch-B commits
b-3
b-2
b-1

…while the upstream is now main.

Note: It’s important that you make sure your local main has that merge commit in it’s history otherwise you’ll end up with weird conflicts.