Question

Background

At work we've been trying to find a new workflow. We currently follow git-flow pretty closely. We don't have release branches; we just merge develop directly into master once we feel like it's well tested enough. When we have a hotfix, we independently merge it into both develop and master.

One of the approaches we've been talking about is that instead of merging develop into master, we instead cherry-pick develop's commits into master. After a few cherry-picks, we deploy it and that's our release. Alternatively we could cherry pick from develop to a release branch (based on master), then merge into master.

At first I was opposed to this, because it would flatten the history out. And, we merge using the --no-ff option, meaning we can revert entire features if needed. This would be lost as well.

Other that that though, I can't really think of any reasons this would be a bad idea. At the same time I can't see any benefits to this approach. But I'm just a mid-level engineer with less than 10 years of professional experience. So I'm really interested in hearing people's experiences / thoughts about this.

Question

Are there benefits to cherry-picking instead of merging? And is there anything that we would lose by using this approach over traditional merging?

Was it helpful?

Solution

Cherry picking commits is useful when you need a specific change in multiple branches where merging other history is not desirable. This is a specific workflow outside of merging, because combining the history of two branches brings over more commits then you need.

Always cherry picking, regardless of the branches involved, defeats the purpose of version control. It keeps history diverged in a system where merging history is desirable, and makes incorporating changes from multiple people easier. Always cherry picking develop to master is an anti pattern with no clear benefit or goal.

This sounds like people are afraid of merging. Cherry picking commits is also merging, but the resulting history of that branch does not recognize that history has been combined. Rather than making history easier to read, if becomes harder to read for the very reason you already have in your question. Merged history, especially if people properly rebase their work before merging or pushing, is easier to read, and trace back in time.

Beyond reading better, a shared history also ensures you do not need to resolve the same merge conflict more than once. For example, I make a change to foo.js on line 25, and this change is in master, but not develop. You make a different change to line 25 of foo.js in develop. Cherry picking my commit from master results in a merge conflict you must resolve manually. Time passes, and you decide it is time to cherry pick that commit from develop to master. Guess what? You get to resolve that merge conflict on line 25 of foo.js again. Will you remember why your change was taken originally? Will the proper change be applied correctly twice, even though nobody has touched foo.js in 2 weeks?

When merging branches, git keeps track of the fact competing changes were made to foo.js, and it remembers how the conflict was resolved so you don't need to do it again.

Every cherry pick is an opportunity to lose history in a version control system hell-bent on retaining history up to the point they had to create a garbage collector for commits that were no longer reachable from a branch (see git gc or git prune).

OTHER TIPS

Typically, we have one branch called develop which is really intended just to be the branch that feature-branches branch off of. Sometimes we merge back onto it, often only after we have also merged the branch into production as described below.

Completed feature branches are merged into a "release candidate" branch of the production branch, and thoroughly tested there. The release candidate branches are then merged into the deployed branch.

Everything that gets merged is always "a complete branch."

The two main trunks run in parallel to one another.

Licensed under: CC-BY-SA with attribution
scroll top