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.
It's simple – before you merge a feature branch back into your main branch (often master or develop ), your feature branch should be squashed down to a single buildable commit, and then rebased from the up-to-date main branch.
Reading the official Git manual it states that rebase “reapplies commits on top of another base branch”, whereas merge “joins two or more development histories together”. In other words, the key difference between merge and rebase is that while merge preserves history as it happened, rebase rewrites it.
If you rebase feature-x on top of origin/develop, you do this on your local repo. This means feature-x is still in the state before rebasing in the remote repository. Since they don't have the same ancestor anymore, git will try to merge. To update the remote branch, you can do a force push.
If you would prefer a clean, linear history free of unnecessary merge commits, you should reach for git rebase instead of git merge when integrating changes from another branch.
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'--H <new_feature / D---E---F---G <develop
Obviously at this point merging new_feature back onto develop can be fast-forwarded like so:
A'--B'--C'--H <new_feature <develop / D---E---F---G
but if it isn't you'll get this instead
A'--B'--C'--H <new_feature / \ D---E---F---G---------------I <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 H
, but I would think git would complain about that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With