Hacker News new | ask | show | jobs
by erso 4792 days ago
There's a simple concept at work here: origin wins.

Whatever is on origin at the moment of you wanting to merge your code is what your code has to work against.

When you use a rebase strategy you're allowed the opportunity to make sure your commits actually work on top of what's on origin, and fix merge issues with those commits as they happened.

So you rebase, run into a conflict, fix the conflict, run your tests, make sure everything's green, and continue the rebase.

When you do the same thing with a merge strategy what happens is you end up fixing the conflicts as part of the merge, and your fixes are hidden in the merge commit.

This means your commits prior to the merge commit are broken. They didn't take into account the work that was on origin at the time, and thus they are useless without considering the conflicts that were resolved during the merge.

The history you describe is not useful unless it's green and could be applied to origin without conflict. The only way to ensure this, both before and after your commits end up on origin is to do so via a rebase strategy.

2 comments

Thank you for this. I cannot believe how many people are glossing over the fact that commits which have to be fixed up in a merge are probably broken. Rebasing is not a way of hiding this, it is a way of _going back and fixing it_.
Thanks for the well reasoned response! Your points are all reasonable, and I understand the pragmatism in wanting only fully-green commits to be on origin. I just think merge commits for logical chunks of work are more important. I read history to understand developer intention and process more than I bisect history to find problems. Those conflicted commits aren't broken, they represent the best effort at the time the changes were made and merely need to be merged together with the world as it is now.
I'm not sure I understand.

If I'm making a change to some code and someone else makes a different change to it and pushes their change to origin before me, I do a rebase and see that they made the change, fix my commit (which is broken at that point in time), resolving the merge conflict, and continue on.

Instead of seeing some changes that have no basis in reality because they were fixed as part of resolving the conflict when doing the merge, you see only their changes applied on top of the correct state of the world, which gives you a clearer idea of what changes they made.

You can still get logical chunks of work with a rebase strategy: you simply rebase on top of the remote and then do a non-fast forward merge, via merge --no-ff.

It's simple: you're into working off of the newest state of the world as much as possible and I'm into working off of a snapshot of the world as much as possible and then merging in my snapshot plus modifications when I'm done. I think your way sounds like it deals with changes to the world more often than I want to, and also loses the context of what your commits looked like when you actually made them, but it's a fine way of doing things, and is especially useful if you're submitting changes to a project for somebody else to merge.