DEV Community

Cover image for There Is No "Right" Way: Git Rebase vs Merge
Molly Struve (she/her)
Molly Struve (she/her)

Posted on

There Is No "Right" Way: Git Rebase vs Merge

In honor of my new license plate, I decided I wanted to do a quick, little post on rebase vs merge, how each one works, and how I choose to use each one. Let's first look at how each one works.

How Rebase and Merge Work

To start we have two branches. We have our master branch and we have a Feature 2 branch that we just cut from master. Both are shown below. Since we just cut our Feature 2 branch it is the exact same as master, nothing has changed yet.

feature and master branches to start

After a couple of days, our Feature 2 branch has some new commits on it with the new feature work that has been done.

feature branch after 2 days

During that same couple of days, the master branch also had a couple of new commits added from another developer who is also working on the project.

master branch after 2 days

Now we are ready to test our Feature 2 branch but before we test it we want to make sure it is updated with all of the new code that is now in master. In order to update our Feature 2 branch with the new changes in master we have two options, we can merge or we can rebase.

Merging

The merge command will let us take all of the development changes present on the master branch and integrate them into the Feature 2 branch with a single merge commit.

merge master

That single merge commit encompasses all of the changes from the master branch. One downside to merging is that if your master branch is very active it can pollute your feature branch’s history quite a bit. If you prefer to not have merge commits in your feature branch history then you might want to consider rebasing.

Rebasing

We can use the rebase command to integrate changes from the master branch into our Feature 2 branch by rewriting the commit history in order to produce a straight, linear succession of commits. Rebasing moves the entire Feature 2 branch to begin on the tip of the master branch.

rebase master

As you can see there are no extra commits and everything is lined up as if we had just added the Feature 2 commits right on top of the new master branch.

My Rebase vs Merge Strategy

When it comes to rebasing vs merging, I use both in different scenarios. When I need to update a feature branch I am working on with master I will ALWAYS rebase. I choose to do this because I like my branch history clean. If all the commits are new code it is easier for me to read and follow. I use merging when it comes time to put my branch changes into master. I like to do this because then I get a single commit that is easy to find with all my branch changes in it.

In my experience, merging when incorporating a feature branch into a master branch is the most common practice when you are working on a repo with a team. How you choose to handle updating your own personal feature branches is usually left up to you and leads me to my next point.

There Is No "Right" Way

Rebasing vs Merging is one of those age-old debates that exist in the dev community much like tabs vs spaces. Also, like tabs vs spaces, when it comes to rebasing vs merging there is no right way to do things. Some people are adamant that you must always merge. Others believe the only correct way to do things is by rebasing. Guess what, neither are right or wrong! How you choose to use rebase vs merge is really up to you and your workflow.

The same concept applies to MANY common dev debates like how many characters a single line should be, how many lines a method should have, etc. Often when you are learning something new all you want to know is the "right" way to do things. You are constantly looking for someone to tell you what to do. Unfortunately, it is not always that easy. When you are starting out, don't look for the right way, look for the way that works best for you. Everyone has their own style and way they work most efficiently. Look around you, soak in what other devs are doing, but in the end decide for yourself what works best.

What other "dev debates" can you think of where both ways work and it's simply personal preference as to which one you choose?

Oldest comments (24)

Collapse
 
khatri_amol profile image
amol khatri

A

Collapse
 
simonhaisz profile image
simonhaisz

Ah, the venomous arguments about trivial things...

On this particular topic, my preference is not to rewrite public history. Rebasing a feature branch that's already on the remote seems wrong to me, so at that point I will always merge master into it. However locally I will rebase most of the time, for all the reasons you outlined here.

Which leads into my example - to squash or not to squash. I've worked with people that think every merge should have a single commit. And others that are just as adamant that you should never rewrite history and every commit should be left the way it was created.

Similar to my merge/rebase preference, I will cleanup my messy local commits by squashing them before pushing. Often I won't squash though because I think the commits are separate things and if I need to revert later on I can be more selective. But what I won't do is squash corrective commits with original commits. If I get feedback on a PR and then I incorporate it I want that history to be preserved. Bizarrely to me, there are some of the 'there shall only be one' committers' who would re-write their branch commits so that changes made after feedback would be incorporated into the same commit as their original changes. They say it's cleaner - to me it's like lying about your work.

Collapse
 
molly profile image
Molly Struve (she/her)

Good call on squash or not to squash argument! That always gets our devs going at Kenna lol

Collapse
 
jessekphillips profile image
Jesse Phillips

The real question is what do you want to get out of your history?

To me history is the why. I like to use the example of undo trees, seen in emacs and vim, these could be view as in memory commits. They have branching and timestamps, but limited in scope to a single file.

The reality is, this isn't the history people keep. They work and craft out a spot they believe is complete. Or they adhere to someone commit twice a day rule. Either way the history is not real.

There are specific tools which make use of history. bisect which searches for a commit. blame which describes a file based on its makeup of commits. revert which is the 'undo' of git, cherry-pick the copy/paste of git. I want to build out a history which maximize the usefulness of these tools.

Git also provides the tools to help with that, staging area, commit --fixup, rebase -i, and more. Fixup is great for code reviews while allowing for quick cleanup before merging.

Yes it doesn't matter, unless your goals line up with mine.

Collapse
 
peterdavidcarter profile image
Peter David Carter • Edited

Regarding squashed changes for me the answer is simple: on larger projects squash, on smaller projects don't. Reason being is on smaller projects having the complete history right there is useful. On larger ones you'll be forced to scroll through dozens, hundreds or even thousands of commits to find even a relatively recent change. No-one wants to do that.

Collapse
 
peterdavidcarter profile image
Peter David Carter

Regarding venomous arguments over trivia seems to me there are a few reasons for this.

The first is that sometimes seeming trivia really does matter.

The second is that some devs lack empathy and can't understand other's preferences.

Following on from these, to non-techies the one can look very much like the other.

Bad devs will often argue personal points on genuine trivia because it makes things nicer for them personally, and since there are likely few real world consequences they don't have to worry about being wrong. Or they just can't tell the difference...

Good and great devs will often still argue trivia for the reason outlined: non-techies and bad devs often can't tell the difference and being seen to be knowledgeable in general can establish them in a position where they can improve the project as a whole, rather than deferring to bad or mediocre devs who would create an inferior product.

Collapse
 
negue profile image
negue

Every time I tried rebase, it screwed up my repo

So since then I stayed on merge 😅

Collapse
 
nicolaerario profile image
Nicola Erario

Very well written! Your strategy is same as the mine; also I never rebase a remote on my local branch

Collapse
 
molly profile image
Molly Struve (she/her)

Thank you! I know many others have done posts on rebasing vs merging but hopefully sharing my perspective and/or explanation will help someone understand it better!

Collapse
 
nicolaerario profile image
Nicola Erario

You can trust me: among all the merge vs rebase post, your is the only comprehensible!

Collapse
 
chathula profile image
Chathula Sampath

Thanks for sharing this way of your working ;) grabbed many things.

Collapse
 
booyaa profile image
Mark Sta Ana

Thank you so much for this super clear explanation! I’ve seen so many posts attempt to do this and fail. Also awesome custom license plate!

Collapse
 
gixxerblade profile image
Steve Clark 🤷‍♀️

Sweet license plate BTW 😋

Collapse
 
cescquintero profile image
Francisco Quintero 🇨🇴

In my initial years doing web development, something weird that used to happen to the team was that sometimes when doing git merge changes would go missing.

This caused the affected pals to be wary of git even to the point of thinking not to use it.

It wasn't until last year(Q4) that I really understood how rebasing works and why that situation happened.

So, I really agree with you that *neither rebase or merge are the right way but rebasing is the way to prevent merges that "remove" code.

How come?

Well, if two devs modify same file, same lines and Dev A pushes to master and then Dev B pulls, if it doesn't do a merge conflict git will remove Dev B changes and place Dev A ones.

I don't really recall the exact conditions for this to happen but it's something like this.

This is when rebasing comes in hand because it kind of respects the commit history and moves rebased commits to the beginning/tip.

Currently, I mostly use git merge but when I feel that situation could happen, I go with git rebase.

👍🏾👍🏾

Collapse
 
mrgung profile image
Steffen Glückselig

No way git loses commits(!) by simply merging. That only happens if Dev B hasn't commited.

Collapse
 
aschwin profile image
Aschwin Wesselius • Edited

When you are starting out, don't look for the right way, look for the way that works best for you.

This.

So, what I get from this article, it makes sense to rebase "downstream" and merge "upstream". I like that. I will be like Molly.

And if it doesn't work, my pragmatic nature will overcome this with ease.

Very straight forward article by the way. Thank you for that.

Collapse
 
andreasjakof profile image
Andreas Jakof

I think I finally understood rebase. 😳

Collapse
 
andreasjakof profile image
Andreas Jakof

To my defense I must add, that I am working with only for a few months now, and never had the usecase for something like rebase.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.