Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

git rebase vs. git merge: an agile perspective

At Pivotal Labs, we’ve been using Quandora for about 6 months as an easier way to archive and discover discussions about the hows and whys of consulting and software engineering here. Earlier this week, I asked my colleagues:

There are some git workflows that would have you regularly work in feature branches and then merge back into master only when the feature is ready for acceptance. However, on every project I’ve worked on at Pivotal, we have preferred to rebase and commit to master regularly.

Why prefer rebasing over merging?

I received some excellent answers.

Rasheed explains:

The more code diverges, the more difficult it is to integrate. If you want continuous integration, it’s a lot easier to do so on one branch, not many. It also drives out stories that are small, have the smallest actionable work, and are easy to accept. This leads to tight feedback loops.

Chad had some information to add to Rasheed’s answer:

Tight feedback loops are one of the things that Pivotal values.

We place priority on CI and small stories. This makes it easier to work on master – it’s not a big deal if it is accidentally broken, it’ll be easily fixed or reverted.

In my experience, we still do use topic branches when appropriate. E.g., in the middle of a story at the end of a day, or for a bigger feature that you don’t want to do in one commit, but would break mainline (master) with the intermediate commit. On my project, in this case, we usually merge –squash –no-commit onto master, to squash multiple commits on the topic branch into one commit on master.

Even in git, branching is still painful. The longer a topic branch lives, the harder it is to merge. Yes, you can rebase often, but that means you have to rewrite history to push the rebased changes to the server. This can cause confusion if the branch lives long and is worked on by multiple pairs or on multiple machines. So, it’s usually less net effort to just work on master, because we have good tests and can trust CI to quickly tell us if there’s any glaring logical merge conflicts that were missed. On teams without CI that rely solely on manual QA, this is much more of a risk and more expensive.

And Jacob, the director of our new Boston office, had this to say:

I’ve seen both patterns at Pivotal. Teams that rebase tend to be small and haven’t had a production release. Large teams have a quickly changing repo and feature branches make the history more readable. And teams that have released use feature branches to relegate incomplete code to a future release. They can also (in theory if not practice) easily roll-back an entire feature branch if something goes wrong in production.

Of course, as Rasheed mentions, trying to wrangle large unreleased changes causes all kinds of problems. Better to get faster feedback with smaller releasable features. If your team still feels it needs to have incomplete features in master, or needs to disable misbehaving pieces of the app, read up about feature switches and look into a tool like rollout or flipper.

So, it seems that in general, we tend to prefer rebasing because it helps facilitate some core concepts of agile software development:

  • Continuous deployment
  • Tight feedback loops
  • Small deliverables

Thanks to Rasheed, Chad, and Jacob for helping provide some great content!

  1. Yawar says:

    I’ve come to think that especially on larger projects, rebasing v merging is very much an art form that you need to develop a feel for.

    But if you want to maintain a tight feedback loop–if you want to _regularly_ make sure your topic branch will integrate with the mainline, there is an alternative to repeated merging or rebasing: the test merge strategy. I’ll quote from a classic article[1] to describe it:

    `The temptation to merge in the mainline during development can be hard to resist; one likes to know whether one’s work is even remotely relevant to the current state of the code. Fortunately, git makes it really easy to create throwaway branches and test out merges and integration there. Once it’s clear that things work, the test branch can be deleted and the (unmerged) development branch sent upstream.’

    I will add here that in case of a merge conflict, you will have to do a bit of git-fu to resolve it on the topic branch while still avoiding a merge/rebase. But it is possible.


Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *