Search code examples
gitgit-mergegit-rebase

Is it true that `rebase' leads to a fewer number of conflicts than `merge'?


From time to time I stumble upon a statement that 'git rebase' leads to a fewer number of conflicts than 'git merge', for example here: Why does git rebase often have fewer merge conflicts than a merge?. Does it mean that there may be situations where git-merge <BRANCH_A> <BRANCH_B> would fail, I would do git reset --hard ORIG_HEAD, then do git-rebase <BRANCH_B> <BRANCH_A> and it would succeed? Can you give me an example of such situation?


Solution

  • The technical difference

    Imagine a history like this:

     A-B-C-D-E  “top-branch”
       \ 
        F-G-H
    

    Now merging E into H means: “take a diff of B‣H and a diff of B‣E and find out how to combine them”.

    Rebasing on the other hand means:

    • take a diff of B‣F and a diff of B‣E and find out how to combine them into F’
    • take a diff of F‣G and a diff of F‣F’ and find out how to combine them into G’
    • take a diff of G‣H and a diff of G‣G’ and find out how to combine them into H’

    So rebasing is exactly the same as merging F, then G and then H into top-branch.

    Now, what does that mean for conflicts?

    The rebase method will do the merge in way more steps. This has advantages and disadvantages.

    Rebase > Merge:

    • Conflicts can be avoided by applying the changes in smaller (more separated) steps
    • The person doing the rebase is applying (probably) their own changes one by one and resolving conflicts therein. Resolving conflicts there might be easier that having to do it all at once.

    Merge > Rebase

    • With a rebase you run a high risk of having to resolve more conflicts, because two changes to the same codeblock that were done in two different commits might result in two conflicts during rebase, but only one in merge. Think about what happens when H is actually a revert of F.
    • Even if you have the same number of conflicts, rebasing is still a more tedious process: You have to open the same file multiple to times to resolve conflicts that happened at different commits.
    • Resolving the conflicts might actually be easier with a merge, because you see all the changes of both branches at once.

    In my opinion rebase is actually the worse process and while that might be possible I am having trouble imagining a situation where it actually avoids conflicts. What seems quite likely is that you have a conflict that is only caused by a one-line change in F. When that codeblock is further changed in G, you might have to resolve all of these changes as one conflict in a merge, but you only have to resolve that one-line change in a rebase. But that is not really a difference, as the conflict will only look bigger, but should be just as easy to resolve.