paint-brush
A Guide to Closing a Pull Request — Merge Commit vs Squash vs Rebase on GitHubby@balastrong
777 reads
777 reads

A Guide to Closing a Pull Request — Merge Commit vs Squash vs Rebase on GitHub

by Leonardo MontiniJanuary 10th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Merging a Pull Request on GitHub has three options: with a merge commit, squash or rebase. In this article, I will go into detail about the three strategies, and I will also do a "live demo" with GitHub stickers and JS pins. But before deciding which strategy to apply you should take some considerations.
featured image - A Guide to Closing a Pull Request — Merge Commit vs Squash vs Rebase on GitHub
Leonardo Montini HackerNoon profile picture

When Merging a Pull Request on GitHub, you mainly have three options: with a merge commit, squash or rebase.

Pull Request Options: Merge, Squash and Rebase


Is there anything wrong with always doing a merge commit? Well, there isn’t right or wrong here, but considering the other strategies might will likely bring you some benefits. Let me tell you why.

In the video, I will go into detail about the three strategies, and I will also do a "live demo" with GitHub stickers and JS pins, if you're curious I'd recommend you to watch the video, otherwise you can find the full-text content here below.


Merge Commit

Merge commit is probably the most common as it’s the default option on GitHub and also the default behaviour when you manually use git merge.


The history of all your commits remains untouched and on the main branch, you see an additional commit that merges all your branch content.


The biggest advantage is that you can easily track down the exact commit where a line has been modified, as long as there aren’t too many commits.


The downside is that when multiple commits are on multiple branches, the history quickly becomes really tangled, and following the path of a change can be quite a challenge.


Merge demo (all commits are kept + 1 merge commit)

Squash merge

The question is, do you really need to keep track of every single commit? Including typos, missing files, and formatting… if the answer is no, then you should consider Squash merge.


When squashing a merge, the result is that you get rid of all commits on the branch and only add a single commit on the main with all the content.


As a result, the history is much cleaner and while working on a branch you can do all the commits you want since you know that with the squash all your sins will be forgotten. Kind of.


Who doesn’t like squash merge, usually brings up the fact that you’re losing a lot of commit history, but it’s up to you if you think commits on a branch are valuable when reviewing old activity or rather is just noise.


Squash Demo (all commits from the feature branch are merged into one commit on main)

Rebase

A third way is that you don’t really need a commit that indicates a merge took place, and you still want to end up having all commits in a single, straight line.


Merge commit has all tangled lines plus an extra commit, Squash is a straight line but loses the history so here comes Rebase, which keeps the history AND the straight line AND doesn’t require an extra commit for the merge.


Does this make Rebase the best strategy ever? Well... actually not necessarily, because it has some potentially destructive side effects.


If you get a merge conflict during a rebase, it’s fairly easy to unintentionally lose parts of your code and if you need to catch up on multiple commits you might end up resolving a merge conflict for every single commit, rather than just one in the other merge strategies.


Rebase demo (all commits from the feature branch are moved to main)

My two cents

After this overview, what do you think? Let me know in the comments!


In my opinion, if branches don’t stay open for a long time, squash merge is a good option, also I’m not a fan of rebase because it’s too easy to make huge mistakes. But before deciding which strategy to apply you should take some considerations.


For example, how often do you and your team have to look back at old commits? How many members are on the team? Does your CI need the full commit history?


Think about it, talk with your team, and you can find together the best strategy for your own use case.


Actually, a good strategy could be subscribing to my YouTube channel if you like my content!

Config

If you want to enforce only some merge strategies on GitHub, head over to the settings of your repository and scroll down a little bit.


Here you will find three sections to allow merge commit, squash, or rebase in your pull requests.


GitHub Pull Requests settings with merge options


If you keep only one selected, all PRs in your repo will be merged with that specific strategy.


For the first two, you can also define the default commit message that can take information from the PR or the commits in the branch in case of a squash.


As you can see rebase doesn’t have this option and the reason is simple. As we just saw, rebasing does not create an extra commit for the merge, so there is nothing to do here. The existing commits are simply moved to the head of your branch.


Since you’re already on this page, if you scroll down a little bit more you might also want to check this flag to automatically delete branches after a PR is merged.


GitHub setting to delete a branch once the Pull Request is merged

Closing

Curious about the photos with the pins and badges? The live demo is on .


But what about you and your team, how do you close your Pull Requests? If you have any preference or want to share your experience, please leave a comment, I'll be really happy to hear from you!


Also published here.