Search code examples
gitmergegithubrebase

When I am using Git, should I rebase before I merge?


I am working on a large scale Rails project, and the team I am working with is using Github to manage the project. While many changes are worked on locally and then pushed directly to our development branch, we create a branch when we are going to work on a very large change. When the time comes to merge that branch back into develop, I often try to rebase develop back into my feature branch before I merge my feature branch into develop (to prevent overwriting of other people's work). I find that when I do this, I seem to run into the same merge conflicts twice. I run into a whole list of conflicts while rebasing, then run into the same list of conflicts again while merging. Should I rebase develop into my feature branch before I merge my feature into develop, or should I just merge my feature into develop?

Let's say my feature branch is called "new_feature". My process for merging it with the "develop" branch goes like this:

git checkout develop 

git pull (this is set up on our rig to always pull rebase)

git checkout new_feature 

git rebase develop 

(lots of merge conflicts ensue) 

git checkout develop  

git merge -no-ff new_feature 

(same set of merge conflicts again)

It's as if the timeline changes from my rebase cause my new feature branch to kind of mirror develop all the way back, and then develop conflicts with a psudo-copy of itself.


Solution

  • OK, this is too long for a comment now.

    To paraphrase the manual (git help rebase)

       Assume the following history exists and the current branch is "new_feature":
    
                     A---B---C new_feature
                    /
               D---E---F---G develop
    
    
       From this point, the result of either of the following commands:
    
           git rebase develop
           git rebase develop new_feature
    
       would be:
    
                             A'--B'--C' <new_feature
                            /
               D---E---F---G <develop
    

    Now, if you had conflicts, the actual state after first running rebase will be

                  A'--B'--C'--[local state]
                 /        ^
    D---E---F---G          new_feature
                ^ develop
    

    where [local state] is the conflicted merge you have yet to fix. Once you've resolved the merge conflicts and added the resolved files to the index, you run git rebase --continue: now your state will be

                  A'--B'--C'' <new_feature
                 /
    D---E---F---G <develop
    

    (where C'' is just C' after fixing conflicts).

    Obviously at this point merging new_feature back onto develop can be fast-forwarded like so:

                  A'--B'--C'' <new_feature  <develop
                 /
    D---E---F---G
    

    but if it isn't you'll get this instead

                  A'--B'--C'' <new_feature
                 /          \
    D---E---F---G------------H <develop
    

    Now whichever of these you prefer from a timeline perspective, it isn't obvious why either would have a problem ... unless you never completed the rebase and resolved the conflicts with C'', but I would think git would complain about that.