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.
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?
…
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.or… make everyone use github. then everyone runs their own sup fork and you only merge changes once they’ve merged your ‘next’ branch into their own feature branches.
If you trust them to make good merging decisions.
Brendan
or… make everyone use github. then everyone runs their own sup fork and you only merge changes once they’ve merged your ‘next’ branch into their own feature branches.
It’s not a question of Github vs not Github. That’s an entirely orthogonal issue. (Maybe one day I’ll write about why I consider Github harmful to one’s code.)
Merging your next into your feature branch is a bad idea, and I would reject merge requests from any feature branches that had such merges in them. Remember, the end goal of a feature branch is to be merged into master, and you don’t want to forcibly pull everything else in next along with it. Maintaining feature branch independence is central to everything I’ve described.
Don’t let the half-assed gittery that you see in your standard Github project confuse you. Look at how Git itself is maintained.
The biggest problem I’ve had, though, is that long-lived topic branches often conflict with each other. This happens both when merging into
nextand when merging intomaster. 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.Have you looked at git-rerere?
“git-rerere – Reuse recorded resolution of conflicted merges
In a workflow employing relatively long lived topic branches, the developer sometimes needs to resolve the same conflicts over and over again until the topic branches are done (either merged to the “release” branch, or sent out and accepted upstream).
This command assists the developer in this process by …"
I haven’t used it myself, but your statement of the problem reminded me of it.
Have you looked at git-rerere?
Yes. To the best of my knowledge git-rerere allows a single developer to reuse conflict resolutions; it doesn’t allow any sharing. Some people mail around the contents of their git-rerere cache as a sharing mechanism, but that seems kinda insane.