Git team workflows: merge or rebase?

The question is simple: In a software team using git and feature branching, what’s the best way to incorporate finished work back to your main line of development? It’s one of those recurring debates where both sides have strong opinions, and mindful conversation can sometimes be hard (for other examples of heated debate see: The Internet).

Should you adopt a rebase policy where the repository history is kept flat and clean? Or a merge policy, which gives you traceability at the expense of readability and clarity (going so far as forbidding fast-forward merges)?

A debate exists

The topic is a bit controversial; maybe not as much as classic holy wars between vim and Emacs, or between Linux and BSD, but the two camps are vocal.

My empirical pulse on all-things-git – scientific, I know! – is that the always merge approach has a slightly bigger mind share. But the always rebase field is also pretty vocal online. For examples see:

To be honest, the split in two camps – always rebase vs. always merge – can be confusing, because rebase as local cleanup is a different thing than rebase as team policy.

Aside: Rebase as cleanup is awesome in the coding lifecycle

Rebase as team policy is a different thing than rebase as cleanup. Rebase as cleanup is a healthy part of the coding lifecycle of the git practitioner. Let me detail some example scenarios that show when rebasing is reasonable and effective (and when it’s not):

With this aside clear we can now talk about policies. I’ll try to keep a balanced view on the argument, and will mention how the problem is dealt with inside Atlassian.

Rebase team policy: definition, pros, and cons

It’s obviously hard to generalize since every team is different, but we have to start from somewhere. Consider this policy as a possible example: When a feature branch’s development is complete, rebase/squash all the work down to the minimum number of meaningful commits and avoid creating a merge commit – either making sure the changes fast-forward (or simply cherry-pick those commits into the target branch).

While the work is still in progress and a feature branch needs to be brought up to date with the upstream target branch, use rebase – as opposed to pull or merge – not to pollute the history with spurious merges.

Pros:

Cons:

NOTE: When history is rewritten in a shared branch touched by multiple developers breakage happens.

Merge team policy: definitions, pros, and cons

Always Merge-based policies instead flow like this: When a feature branch is complete merge it to your target branch (master or develop or next).

Make sure the merge is explicit with –no-ff, which forces git to record a merge commit in all cases, even if the changes could be replayed automatically on top of the target branch.

Pros:

Cons:

Decisions, decisions, decisions: What do you value most?

So what’s best? What do the experts recommend?

If you and your team are not familiar with, or don’t understand the intricacies of rebase, then you probably shouldn’t use it. In this context, always merge is the safest option.

If you and your team are familiar with both options, then the main decision revolves around this: Do you value more a clean, linear history? Or the traceability of your branches? In the first case go for a rebase policy, in the later go for a merge one.

Note that a rebase policy comes with small contraindications and takes more effort.

At Atlassian

The policy inside Atlassian’s Stash team is always to merge feature branches, and require that branches are merged through a pull request for quality and code review. But the team is not too strict around fast-forward.

Conclusions and acknowledgements

This article is the result of the confluence of insightful exchanges (pun intended!) with the Stash team on the topic.

This piece hopefully dispels the doubts on this, and allows you to adopt an approach that works for your team. Follow me @durdn for more git awesomeness.

 

Anyone can be good, but awesome takes teamwork.

Find tools to help your team work better together in our Git Essentials solution.

Exit mobile version