Git rebase conflicts
This video explains whether git rebase has more conflicts than git merge, detailing the differences between the two commands, how conflicts arise in each scenario, and best practices for managing and resolving these conflicts effectively.
I see many developers struggle with using git rebase and I think the main reason of the struggle is
caused by the conflicts that arise when rebasing.
So right from the start let’s clarify something:
Does git rebase has more conflicts than merge?:
The answer is if you know what you are doing than usually no - the number of conflicts will be the same.
The know what you are doing is often the problem.
If you are working in a branch and your commits are messy (We will explain what messy means) then you will have tons of conflicts when working with rebase.
In this article we will try and understand how git rebase works, and why we have so many conflicts when rebasing.
Rebase and Merge
Section titled “Rebase and Merge”Let’s start by understanding what git rebase and git merge are doing.
Our starting point is that we started from a branch called main.
We wanted to work on a new feature, so we created a new branch called feature.
We created a few commits on the feature branch and while we were working on the branch, the main branch was updated with new commits.

we are on the feaure branch and we want to get the new commits from main into our feature branch we can do one of two things:
- We can use git mergeto merge themainbranch into ourfeaturebranch.
git merge mainThis assumes we are on the feature branch.
- We can use git rebaseto rebase ourfeaturebranch on top of themainbranch.
git rebase mainLet’s try and understand what each of these commands does.
Git Merge
Section titled “Git Merge”When we run git merge main we are telling git to merge the main branch into our current branch.
Git will create a new commit that combines the changes from both branches.
This new commit will have two parents: the last commit on the main branch and the last commit on the feature branch.

Notice that a new commit was added on the feature branch.
Conflicts with Merge
Section titled “Conflicts with Merge”Let’s examine the image above and imagine that on the feature branch in commit 1 we installed some package using npm install <some-package1>.
Then in the same branch in commit 3 we installed another package using npm install <some-package2>.
So in commit 1 and commit 3 we have changes in the package.json file.
Now let’s imagine in the main branch in commit C another developer installed a package using npm install <some-package3>.
So in commit C we also have changes in the package.json file.
Now when we try to merge the main branch into our feature branch, there is a good chance that we will have a conflict in the package.json file.
Let’s define 2 concepts that relate to conflicts and their value when doing a merge:
- ours- the changes that we made in our branch (the- featurebranch).
- theirs- the changes that were made in the other branch (the- mainbranch).
In the following conflict we will have a conflict on the package.json file, where ours is the aggregated change in package.json from commit 1 and commit 3 and theirs is the change in package.json from commit C.
So we will have one conflict to solve on the package.json file.
Git Rebase
Section titled “Git Rebase”When we run git rebase main we are telling git to take all the commits from the feature branch and replay them on top of the main branch.
Git will take each commit from the feature branch and apply it on top of the main branch.
This means that the commits from the feature branch will be added to the main branch one by one.

Conflicts with Rebase
Section titled “Conflicts with Rebase”Same conflict scenario as before. we installed some package using npm install <some-package1> in commit 1 and in commit 3 we installed another package using npm install <some-package2>.
In the main branch in commit C another developer installed a package using npm install <some-package3>.
Let’s define 2 concepts that relate to conflicts and their value when doing a rebase - Notice that the ours and theirs are different than the merge:
- ours- represet the branch that we rebase on top of (the- mainbranch).
- theirs- represent the commit that we are trying to rebase (the- featurebranch).
Now here is the catch:
When we rebase we might have conflicts on every commit that we are trying to rebase.
So in our case we will have a conflict on commit 1 that introduced a change in package.json that we will have to solve before the rebase can continue.
Then we will have to solve another conflict on package.json in commit 3.
This means that in our Rebase example we had to solve 2 conflicts on the package.json file, while in the Merge example we only had to solve one conflict on the package.json file.
It seems from this example that git rebase has more conflicts than git merge.
OR IS IT?
git rebase interactive mode
Section titled “git rebase interactive mode”Rebase interactive mode gives you a chance to edit the commits that you are rebasing. You can change the commit message, squash commits, drop commits, reorder commits, and more. There are times when we code something commit and then after few commits in the future we realize that a commit we made had issues and needs a bit of change. We can fix the issue and create a new commit but that’s not always the best solution.
Let’s try to explain the problem with an example.
Let’s say you have a task where you need to install a package that will help you with PDF files, and using that package you will have
to read the pdf, and search for a specific string.
So here is the workflow of the task:
- You find a popular package pdf-readerand you install it. You create your first commitchore: install pdf-reader.
- You implement reading the pdf and create another commit feat: read pdf.
You find out that the package you chose cannot be used for searching for a string in the pdf.
You decide to go with a different package pdf-lib that can do the job.
- you create a new commit chore: install pdf-lib.
- You implement reading the pdf and create a commit
- You implement searching for a string in the pdf and create another commit.
Then you realize that the package you chose are not maintained and has a lot of issues.
The you decide to go with a 3rd package awesome-pdf which you manage to create all the features you need.
So a commit history in your branch might look like this:

That trial and error is not necessarily something you want to keep in your commit history, and at times can be sufficent just placing a trial you did in a commit body instead of creating a full commit. For example that same commit history can be arranged differently using git rebase interactive mode:

I would argue that the second commit history is much cleaner and easier to understand. And what about conflicts?
If we take the previous example that we had a conflict on the package.json, in the example where we don’t arrange and squash our commits properly
we might have conflicts like the number of commits that changed the package.json file.
Which means in this example we will have 3 conflicts, on the other hand after arranging and squashing our commits we will have only one conflict on the package.json file because only one commit is changing that file.
And to give a few examples how to arrange and maintain a clean commit history, we highly recommend to read a tutorial we wrote on the topic: Clean your commits
Convlicts Rebase vs Merge
Section titled “Convlicts Rebase vs Merge”So actually if we make sure to arrange our commits properly and squash them when needed, then most likely the number of conflicts we will have when rebasing will be the same as the number of conflicts we will have when merging. The only difference might be if there is changes in the same file that the developer wants to emphasize the changes in different commits. Changes that are not related to each other and are more suited to a different commit then a remark on the commit body. Have to say that those are relatively rare, especially if you arrange you work properly to PR’s with single responsibility and not a single PR that does everything. But there are cases when developer choose to split a change on a single file into multiple commits, in that case yes there will be more conflicts, but those changes are aimed for different pr’s it makes sense that those changes will be reflected multiple times if that was the choice of the developer. On the merge side you will suddently have a commit with solved conflicts that reflect different commits from the past, very confusing in terms of looking back at the commit history.
So bottom line if you arrange your PR properly 99% of the time - same conflicts, the 1% is your choice but it’s actually better in terms of commit history.
What about pull?
Section titled “What about pull?”To understand how pull affects in terms of conflicts, rebase, and merge, let’s think about the following scenario:
I’m on a branch called feature I create 3 commits on that branch.
commit 1 and commit 3 are changing the same file package.json.
On the main branch a developer pushed a commit with changes to the package.json file.

This image describe the scenario, we want to examine what happens on different pull commands.
git pull
Section titled “git pull”git pull with no additional argument will pull from the upstread branch (provided there is one) and merge the changes into the current branch.
Meaning if we are on the feature branch and we run git pull it will git fetch to get the latest changes to the local repository and then it will merge the changes into the feature branch from the upstream of the feature branch (usually origin/feature).
so provided that your remote name is origin and the upstream branch is origin/feature, the command will be equivalent to:
git fetch origingit merge origin/featureand a more explicit command would be:
git pull origin featurewhich in this case will be equivalent.
git pull origin main
Section titled “git pull origin main”If I’m on the branch feature and I run git pull origin main, it will fetch the changes from the main branch and merge them into the feature branch.
This is equivalent to running:
git fetch origin maingit merge origin/mainThis means that the changes from the main branch will be merged into the feature branch.
Merge meaning another commit will be created on the feature branch that will combine the changes from both branches.
Notice that the main branch is updated in our local repository but not in the working directory, so if we transition to main we won’t see the changes.
We will have to run git pull to get the changes from the main branch into our local repository.
git pull —rebase
Section titled “git pull —rebase”You can also run git pull with the --rebase option.
So if we are on the feature branch and we run:
git pull --rebase origin mainThis will fetch the changes from the upstream branch and rebase the current branch on top of the upstream branch. This is equivalent to running:
git fetch origin maingit rebase origin/main # we are currently on the feature branchNotice that the working directory is not updated with the changes from the main branch.
This means the if we transition to the main branch we won’t see the changes until we run git pull to get the changes from the main local repository to the working directory.
without the --rebase option the default behavior of git pull is to merge the changes from the upstream branch into the current branch.
Since I prefer to use rebase instead of merge I can set the default behavior of git pull to rebase by running:
git config pull.rebase trueIn general I do find it clearer if the working directory is updated with the changes from the upstream branch and local repository, so personally I prefer not to do a git pull origin main  directly to my feature branch.
I prefer to do a git pull origin main to the main branch and then do a git rebase main to my feature branch.
Some developers might look at it as a bit more work, but I find it clearer and easier to understand.
Conclusion
Section titled “Conclusion”If your PR branch is organized properly and you are using git rebase instead of git merge then the number of conflicts you will have when rebasing will be the same as the number of conflicts you will have when merging.
With Rebase there are certain changes in the same file that you choose not to squash to emphasize some change, on those not that common occasions that specific file can have more than
one conflict, but it does make the history cleaner and easier to understand and those changes you want to emphasize are more understandable
if the commit is solved on that specific commit and not one time on the merged version of the change.