5 min read
Jan. 5, 2024
If you are new to git knowing when to use git rebase vs merge can be difficult. Everyone seems to have their own opinion (myself included) on which one is better. I'll try to do a quick walk through of the basics of both, talk about which one I like and why (hint: rebase) and some pros vs cons on both.
Before we get started though I should mention that it's likely going to become a preference for either yourself or your team on which one you end up using most. I've been on teams that are strict rebase teams and others that want to preserve every commit so they are merge only. It really will be up to you and the team at the end of the day and hopefully I outline the merits of both.
# make sure you have latest updates from main
git checkout main
git pull origin main
# now checkout branch and rebase
git checkout feature-branch-name
git rebase -i main
The above code is the essence of how you can start a git rebase. From your feature branch, run the rebase command and it will get you started. I personally prefer to run it with the -i flag to make the rebase interactive.
Interactive means you can see a list of the commits that will be rebased on top of the main branch. You can also choose to either squash, fixup, etc. the commits right here in case there are a few you want to not keep the commit messages for.
If this is all sounding like gibberish I will start with a (hopefully) decent visual. Imagine you cut a deck of cards. The cards that you cut are the commits you want to put into the main branch. You will put the cards on top of the deck. Meaning that your commits will go on top of every commit on main, no matter if your commits are older than what is already in the main branch. You are essentially putting all of your commits on the top of the history (more on this later) in one big chunk.
^^ your commits going on top of everything else in the repo
Some people prefer this method because it keeps all of the commits for a feature in one big chunk. It can also be a bit easier to fixup, squash, etc. commit messages using the interactive flag discussed above if you wanted just one giant commit for your feature branch.
Others don't like the it rewrites the history of your branch. The history is basically all of the work that has already happened on the branch and what has happened previously. When you rebase you are technically putting your history over everything that's already on the branch which isn't technically a 100% accurate depiction of exactly when a commit was done.
It should also be noted that because you are rewriting history you will need to force push your feature branch. Note: In no circumstances should you ever force push on any branches that multiple people are working on, particularly development or main. Rewriting the history for other people that are working on the same branch as you can cause a whole bunch of nightmares. It is best to only use on a feature branch you are working on by yourself. To do this run:
git push --force origin feature-branch-name
Now you've rebased your branch, go ahead and open up that PR!
# merging into main
git checkout main
git merge feature-branch-name
# merging main into a branch you are working on to keep it updated
git checkout feature-branch-name
git merge main
Merging in my experience seems to be more popular. When you open a PR on Github and click merge, a commit is created on the branch you are merging into that signals you have merged a branch into another.
When working on a feature branch you will often need to make sure your branch is kept up to date with what is happening throughout the repo. To do this you will run the second set of commands from above and keep merging main into your branch. Like merging a PR, when you run the merge command you will create a commit message on your feature branch that says something to the effects of "merged main into feature branch" so you know what happened.
With merging you never overwrite the history of the repo. The one drawback is that if you are working on a branch for a long time you may have many commits that are just merging main into your feature branch. If there are any merge conflicts you will also have to deal with them all at once which isn't necessary a drawback, but just something to be aware of.
To continue with the deck of cards visual imagine you have two stacks of cards. This time instead of putting one on top of the other you push the two decks together so they intertwine with each other. That is functionally what happens when you merge your branch into another. Any commits that happened on the branch you are merging in will be merged in sequential order. This intertwines your commits with everything else happening in the repo.
This visual is a bit harder to explain as a deck of cards doesn't have the concept of sequential order, but the visual of merging two stack of cards together I think holds up decently well.
I personally prefer using rebase as I prefer dealing with merge conflicts in the rebase workflow. I tend to always rebase my branches before creating a pull request, then will merge my changes into development/main. It's a workflow that I enjoy, but have had to change depending on what my team prefers. Typically you can choose what works best for you, but I have worked with some who want to preserve all history which I also get. If you are new to git try out both methods and see what clicks!