Sharing Conflict Resolutions in Git

Development of Sup is done with Git. Sup follows a topic branch methodology: features and bugfixes typically start off as “topic” branches from master, and are merged into an “integration”/“version” branch next for integration testing. After n cycles of additional bugfix commits to the topic branch, and re-merges into next, the topic branches are finally merged down to master, to be included in the next release.

I really like this approach because I think it evinces the real power of Git: that merges are so foolproof that I can pick and choose, on a feature-by-feature basis, which bits of code I want at each level of integration. That’s crazy cool. And users can stick to master if they want something stable, and next if they want the latest-and-greatest features.

The biggest problem I’ve had, though, is that long-lived topic branches often conflict with each other. This happens both when merging into next and when merging into master. I don’t think there’s a way around it; isolating features in this way has all the benefits above, but it also means that when they touch the same bits of code, you’ll get a conflict.

As a lazy maintainer, the biggest question I’ve had is: is there a way to push the burden of conflict resolution to the patch submitter? Is there a way for me to say: hey, your change conflicts with Bob’s. Can you resolve the conflict and send it to me?

One option I’ve considered is to have contributors to publish not only their feature branches, but their next branch as well. Assuming they aren’t mucking about with their next branch otherwise, if it contains just the merge commit, I can merge it into mine, and it should be a fast-forward that gets me the merge commit, conflict resolution and all.

But I don’t like that idea because, in every other case, I’m merging in the feature branches directly. Why should I suddenly start merging in next just because you have a conflict?

Furthermore, Sup primarily receives email contributions via git format-patch, and I do the dirty deed of sorting them into branches and merging things around. Requiring everyone to host a git repo iff they produce a conflicting patch seems silly. (And git format-patch, unfortunately, produces nothing for merge commits, even if they have conflict resolution changes. Maybe there’s a good reason for this, or maybe not. I’m not sure.)

After some effort, and some git-talk discussion, I have a solution. And no, it doesn’t involve sharing git-rerere caches. (Which it seems that some people do!)

For the contributor: once you have resolved the conflict, do a git diff HEAD^. This will output the conflict resolution changes. Email that to the maintainer along with your patch.

For the maintainer:

$ git checkout next
$ git merge <offending branch>
[... you have a conflict, yada yada ...]
$ git checkout next .
$ git apply --index <resolution patch filename>
$ git commit

Running git merge gets you to the point where you have a conflict. Running git checkout next . sets your working directory to the state it was before you merged. And git apply applies the resolution changes.

You lose authorship of the conflict resolution, but you can use git commit --author to set it.

I think the ideal solution would be for git format-patch to produce something usable in this case. I see some traffic on the Git list that suggests this is being considered, so hopefully one day this rigmarole will not be necessary.

To reply to the article, enter your email address. A copy of the article will be sent to you via email.