the all-thing | 2010-09-04 17:16:05 -0400 ========================================== Sharing Conflict Resolutions in Git ----------------------------------- Date: March 22, 2009 5:23pm Author: William Morgan Labels: git, sup URL: http://all-thing.net/git-conflict-resolution.txt Development of Sup [1] 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 [... you have a conflict, yada yada ...] $ git checkout next . $ git apply --index $ 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. [1] http://sup.rubyforge.org/ Replies -------- Brendan O'Connor, on March 23, 2009 6:45pm: ["| ...\n", "| \n", "| or... make everyone use github. then everyone runs their own sup fork and you\n", "| only merge changes once they've merged your 'next' branch into their own\n", "| feature branches.\n", "| \n", "| If you trust them to make good merging decisions.\n", "| \n", "| Brendan\n", "| \n"] William Morgan, on March 23, 2009 6:59pm: [" | \n", " | It's not a question of Github vs not Github. That's an entirely orthogonal\n", " | issue. (Maybe one day I'll write about why I consider Github harmful to one's\n", " | code.)\n", " | \n", " | Merging your next into your feature branch is a bad idea, and I would reject\n", " | merge requests from any feature branches that had such merges in them.\n", " | Remember, the end goal of a feature branch is to be merged into master, and\n", " | you don't want to forcibly pull everything else in next along with it.\n", " | Maintaining feature branch independence is central to everything I've\n", " | described.\n", " | \n", " | Don't let the half-assed gittery that you see in your standard Github project\n", " | confuse you. Look at how Git itself is maintained.\n", " | \n"] Evan Martin, on November 15, 2009 6:13pm: ["| \n", "| Have you looked at git-rerere?\n", "| \n", "| \"git-rerere - Reuse recorded resolution of conflicted merges\n", "| \n", "| In a workflow employing relatively long lived topic branches, the developer\n", "| sometimes needs to resolve the same conflicts over and over again until the\n", "| topic branches are done (either merged to the \"release\" branch, or sent out\n", "| and accepted upstream).\n", "| \n", "| This command assists the developer in this process by ...\"\n", "| \n", "| I haven't used it myself, but your statement of the problem reminded me of it.\n"] William Morgan, on November 15, 2009 6:24pm: [" | \n", " | Yes. To the best of my knowledge git-rerere allows a single developer to reuse\n", " | conflict resolutions; it doesn't allow any sharing. Some people mail around\n", " | the contents of their git-rerere cache as a sharing mechanism, but that seems\n", " | kinda insane.\n", " | \n"] This delicious text version served up by Whisper .