<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
  <title>the all-thing</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" href="/static/style.css" type="text/css" />
  <link rel="alternate" type="application/rss+xml" title="the all-thing RSS feed" href="/index.rss" />
  <link rel="alternate" type="text/plain" title="the all-thing in plain text" href="/index.txt" />
  <script type="text/javascript" src="/static/mootools.js"></script>
  <script type="text/javascript" src="http://music.masanjin.net:9292/waxiest.js"></script>
</head>
<body>

<div id="main">
  <div id="header">
    <h1><a  href="/">the all-thing</a></h1>
    
  </div>
  <div id="sidebar">
    <h3>Recent comments</h3>

    <ul class="sidebar-list">
    
    <li><b><a  href="/whisper-0.5#58174069c046a78e55f02ef81da81e74">Dominique Julia</a></b>
        <i><a  href="/whisper-0.5">Whisper 0.5 released</a></i>
           one week ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#8fa2a0f392d7c0562d630e4936407c11">William Morgan</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#533654a7a229569e27a6d0afd716c444">William Morgan</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#b7b7a905477674eb6985b34a964a0dca">Joao Nelas</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#b00001114360ac152f87d4ac2a6e0c5b">Ollivier Robert</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    </ul>

    <h3>Authors</h3>
    <ul class="sidebar-list">
    
      <li><a class="author" href="/by/William+Morgan/">William&nbsp;Morgan</a>&nbsp;(65) </li>
    
    </ul>

    <h3>Tags</h3>
    <ul class="sidebar-list">
    
      <li><a class="label" href="/label/releases/">releases</a>&nbsp;(15) </li>
    
      <li><a class="label" href="/label/whisper/">whisper</a>&nbsp;(13) </li>
    
      <li><a class="label" href="/label/git/">git</a>&nbsp;(9) </li>
    
      <li><a class="label" href="/label/stats/">stats</a>&nbsp;(8) </li>
    
      <li><a class="label" href="/label/trollop/">trollop</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/ruby/">ruby</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/sup/">sup</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/git-wtf/">git-wtf</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/vm/">vm</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/mathml/">mathml</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/continuations/">continuations</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/ditz/">ditz</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/proglang/">proglang</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/optimization/">optimization</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/benchmarks/">benchmarks</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/rubinius/">rubinius</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/inlining/">inlining</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ubuntu/">ubuntu</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/fibers/">fibers</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ritex/">ritex</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ruby1.9/">ruby1.9</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ncurses/">ncurses</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/javascript/">javascript</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/media/">media</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/vim/">vim</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/classification/">classification</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/massachusetts/">massachusetts</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/greasemonkey/">greasemonkey</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/wine/">wine</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/readme/">readme</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/ancient-greek/">ancient-greek</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/web/">web</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/current+events/">current&nbsp;events</a>&nbsp;(1) </li>
    
    </ul>

    <h3>Other formats</h3>
    <ul class="sidebar-list">
    <li><a href="/index.rss"><img src="/static/rss-badge.png"/></a></li>
    <li><a href="/index.txt">plain text version</a></li>
    </ul>

    <h3 class="waxiest.author.original">Who is this man?</h3>
    <h3 class="waxiest.author.beautiful" style="display:none">I must find out more about this beautiful creature</h3>
    <h3 class="waxiest.author.beautifulbig" style="display:none">I MUST FIND OUT MORE ABOUT THIS BEAUTIFUL CREATURE</h3>
    <h3 class="waxiest.author.originalbig" style="display:none">WHO IS THIS MAN?</h3>

    <script type="text/javascript">
      var w = waxiest();
      w.optimizeHTMLSection("author", ["original", "beautiful", "beautifulbig", "originalbig"]);
    </script>

    <a href="http://masanjin.net" onClick="w.goalReached('greeting')">William Morgan</a>
  </div>
  <div id="content">
    <h2><a  href="/git-conflict-resolution">Sharing Conflict Resolutions in Git</a></h2>

<div class="byline">
  <a  href="/by/William+Morgan/">William Morgan</a>,
  <span title="11 months ago">March 22, 2009  5:23pm</span>
</div>

  <div class="labels"><span class='label'><a  href="/label/git/">git</a></span> <span class='label'><a  href="/label/sup/">sup</a></span> </div>


<p class='first'>Development of <a href="http://sup.rubyforge.org/">Sup</a> is done with Git. Sup follows a
<em>topic branch</em> methodology: features and bugfixes typically start off as
&#8220;topic&#8221; branches from <code>master</code>, and are merged into an &#8220;integration&#8221;/&#8220;version&#8221;
branch <code>next</code> for integration testing. After <em>n</em> cycles of additional bugfix
commits to the topic branch, and re-merges into <code>next</code>, the topic branches are
finally merged down to <code>master</code>, to be included in the next release.</p>
<p>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&#8217;s crazy cool. And users can stick to <code>master</code> if they want
something stable, and <code>next</code> if they want the latest-and-greatest features.</p>
<p>The biggest problem I&#8217;ve had, though, is that long-lived topic branches often
conflict with each other. This happens both when merging into <code>next</code> and when
merging into <code>master</code>. I don&#8217;t think there&#8217;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&#8217;ll get a conflict.</p>
<p>As a lazy maintainer, the biggest question I&#8217;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&#8217;s. Can you resolve the conflict and
send it to me?</p>
<p>One option I&#8217;ve considered is to have contributors to publish not only their
feature branches, but their <code>next</code> branch as well. Assuming they aren&#8217;t mucking
about with their <code>next</code> 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.</p>
<p>But I don&#8217;t like that idea because, in every other case, I&#8217;m merging in the
feature branches directly. Why should I suddenly start merging in <code>next</code> just
because you have a conflict?</p>
<p>Furthermore, Sup primarily receives email contributions via <code>git format-patch</code>,
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 <code>git format-patch</code>, unfortunately, produces nothing for
merge commits, even if they have conflict resolution changes. Maybe there&#8217;s a
good reason for this, or maybe not. I&#8217;m not sure.)</p>
<p>After some effort, and some git-talk discussion, I have a solution. And no, it
doesn&#8217;t involve sharing <code>git-rerere</code> caches. (Which it seems that some people
do!)</p>
<p>For the contributor: once you have resolved the conflict, do a <code>git diff
HEAD^</code>. This will output the conflict resolution changes. Email that to the
maintainer along with your patch.</p>
<p>For the maintainer:
<code><pre class="ruby"><span class="global">$ </span><span class="ident">git</span> <span class="ident">checkout</span> <span class="keyword">next</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">merge</span> <span class="punct">&lt;</span><span class="ident">offending</span> <span class="ident">branch</span><span class="punct">&gt;</span>
<span class="punct">[...</span> <span class="ident">you</span> <span class="ident">have</span> <span class="ident">a</span> <span class="ident">conflict</span><span class="punct">,</span> <span class="ident">yada</span> <span class="ident">yada</span> <span class="punct">...]</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">checkout</span> <span class="keyword">next</span> <span class="punct">.</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">apply</span> <span class="punct">--</span><span class="ident">index</span> <span class="punct">&lt;</span><span class="ident">resolution</span> <span class="ident">patch</span> <span class="ident">filename</span><span class="punct">&gt;</span>
<span class="global">$ </span><span class="ident">git</span> <span class="ident">commit</span></pre></code></p>
<p>Running <code>git merge</code> gets you to the point where you have a conflict. Running
<code>git checkout next .</code> sets your working directory to the state it was before
you merged. And <code>git apply</code> applies the resolution changes.</p>
<p>You lose authorship of the conflict resolution, but you can use <code>git commit
--author</code> to set it.</p>
<p>I think the ideal solution would be for <code>git format-patch</code> 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.</p>

<h4>Discussion</h4>
<a name="comments"></a>

<ul class="comment-tree">

  <li>
  
  <a name="08bc2f04fd5864324c7db5debe16d503"></a>
  <div class="comment-body">
    <table class="comment-byline">
      <tr><td class="comment-author">Brendan O'Connor</td>
          <td class="comment-date" title="11 months ago"><a href="#08bc2f04fd5864324c7db5debe16d503">March 23, 2009  6:45pm</a></td>
    </tr></table>
    <div class='comment-quote'>
<p class='first'>As a lazy maintainer, the biggest question I&#8217;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&#8217;s. Can you resolve the conflict and
send it to me?</p>
</div><p>&#8230;</p><div class='comment-quote'>
<p>For the contributor: once you have resolved the conflict, do a <code>git diff
HEAD^</code>. This will output the conflict resolution changes. Email that to the
maintainer along with your patch.</p>
</div><p class='first'>or&#8230; make everyone use github.  then everyone runs their own sup fork
and you only merge changes once they&#8217;ve merged your &#8216;next&#8217; branch into
their own feature branches.</p>
<p>If you trust them to make good merging decisions.</p>
<p>Brendan</p>
    <div class="reply-to-outer">
      <div class="reply-to-header"><a href="#" class="reply-to-link">reply</a></div>
      <div class="reply-to-box" id="reply-to-git-conflict-resolution-08bc2f04fd5864324c7db5debe16d503" >
        <span class="comment-instructions">To reply, enter your email address. A copy of the comment will be sent to you via email.</span>
        <form id='comment-form-git-conflict-resolution-08bc2f04fd5864324c7db5debe16d503' action='/comment/git-conflict-resolution' method='post' class='comment-form'>
          <input type='text' name='email' id='textfield-email'/>
          <input type='submit' value='email me' id='submit-email me'/>
        <input type='hidden' name='comment-id' value='08bc2f04fd5864324c7db5debe16d503'/>
  <span class="form-result" id="form-result-git-conflict-resolution-08bc2f04fd5864324c7db5debe16d503"><!-- spanna --></span>
</form>

      </div>
    </div>
  </div>

  <ul><li>
  
  <a name="6eb37dc39d6bb79aef22a4a1bc397fcd"></a>
  <div class="comment-body">
    <table class="comment-byline">
      <tr><td class="comment-author"><a href="http://masanjin.net/">William Morgan</a></td>
          <td class="comment-date" title="11 months ago"><a href="#6eb37dc39d6bb79aef22a4a1bc397fcd">March 23, 2009  6:59pm</a></td>
    </tr></table>
    <div class='comment-quote' title="Reformatted excerpts from Brendan's message of 2009-03-23:">
<p>or&#8230; make everyone use github.  then everyone runs their own sup fork
and you only merge changes once they&#8217;ve merged your &#8216;next&#8217; branch into
their own feature branches.</p>
</div><p class='first'>It&#8217;s not a question of Github vs not Github. That&#8217;s an entirely
orthogonal issue. (Maybe one day I&#8217;ll write about why I consider Github
harmful to one&#8217;s code.)</p>
<p>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&#8217;t want to forcibly pull everything else in next
along with it. Maintaining feature branch independence is central to
everything I&#8217;ve described.</p>
<p>Don&#8217;t let the half-assed gittery that you see in your standard Github
project confuse you. Look at how Git itself is maintained.</p>
    <div class="reply-to-outer">
      <div class="reply-to-header"><a href="#" class="reply-to-link">reply</a></div>
      <div class="reply-to-box" id="reply-to-git-conflict-resolution-6eb37dc39d6bb79aef22a4a1bc397fcd" >
        <span class="comment-instructions">To reply, enter your email address. A copy of the comment will be sent to you via email.</span>
        <form id='comment-form-git-conflict-resolution-6eb37dc39d6bb79aef22a4a1bc397fcd' action='/comment/git-conflict-resolution' method='post' class='comment-form'>
          <input type='text' name='email' id='textfield-email'/>
          <input type='submit' value='email me' id='submit-email me'/>
        <input type='hidden' name='comment-id' value='6eb37dc39d6bb79aef22a4a1bc397fcd'/>
  <span class="form-result" id="form-result-git-conflict-resolution-6eb37dc39d6bb79aef22a4a1bc397fcd"><!-- spanna --></span>
</form>

      </div>
    </div>
  </div>

  </li></ul></li><li>
  
  <a name="84a77ca9bdea229b100da32ae6eeb621"></a>
  <div class="comment-body">
    <table class="comment-byline">
      <tr><td class="comment-author">Evan Martin</td>
          <td class="comment-date" title="three months ago"><a href="#84a77ca9bdea229b100da32ae6eeb621">November 15, 2009  6:13pm</a></td>
    </tr></table>
    <div class='comment-quote' title="On Sun, Nov 15, 2009 at 9:57 AM, William Morgan &lt;comments@all-thing.net&gt; wrote:">
<p class='first'>The biggest problem I&#8217;ve had, though, is that long-lived topic branches often
conflict with each other. This happens both when merging into <code>next</code> and when
merging into <code>master</code>. I don&#8217;t think there&#8217;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&#8217;ll get a conflict.</p>
</div><p class='first'>Have you looked at git-rerere?</p>
<p>&#8220;git-rerere &#8211; Reuse recorded resolution of conflicted merges</p>
<p>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
&#8220;release&#8221; branch, or sent out and accepted upstream).</p>
<p>This command assists the developer in this process by &#8230;&quot;</p>
<p>I haven&#8217;t used it myself, but your statement of the problem reminded me of it.</p>
    <div class="reply-to-outer">
      <div class="reply-to-header"><a href="#" class="reply-to-link">reply</a></div>
      <div class="reply-to-box" id="reply-to-git-conflict-resolution-84a77ca9bdea229b100da32ae6eeb621" >
        <span class="comment-instructions">To reply, enter your email address. A copy of the comment will be sent to you via email.</span>
        <form id='comment-form-git-conflict-resolution-84a77ca9bdea229b100da32ae6eeb621' action='/comment/git-conflict-resolution' method='post' class='comment-form'>
          <input type='text' name='email' id='textfield-email'/>
          <input type='submit' value='email me' id='submit-email me'/>
        <input type='hidden' name='comment-id' value='84a77ca9bdea229b100da32ae6eeb621'/>
  <span class="form-result" id="form-result-git-conflict-resolution-84a77ca9bdea229b100da32ae6eeb621"><!-- spanna --></span>
</form>

      </div>
    </div>
  </div>

  <ul><li>
  
  <a name="45770d783cfea6b30ec2a4a46a3481b5"></a>
  <div class="comment-body">
    <table class="comment-byline">
      <tr><td class="comment-author"><a href="http://masanjin.net/">William Morgan</a></td>
          <td class="comment-date" title="three months ago"><a href="#45770d783cfea6b30ec2a4a46a3481b5">November 15, 2009  6:24pm</a></td>
    </tr></table>
    <div class='comment-quote' title="Reformatted excerpts from Evan Martin (on the all-thing)'s message of 2009-11-15:">
<p>Have you looked at git-rerere?</p>
</div><p class='first'>Yes. To the best of my knowledge git-rerere allows a single developer to
reuse conflict resolutions; it doesn&#8217;t allow any sharing. Some people
mail around the contents of their git-rerere cache as a sharing
mechanism, but that seems kinda insane.</p>
    <div class="reply-to-outer">
      <div class="reply-to-header"><a href="#" class="reply-to-link">reply</a></div>
      <div class="reply-to-box" id="reply-to-git-conflict-resolution-45770d783cfea6b30ec2a4a46a3481b5" >
        <span class="comment-instructions">To reply, enter your email address. A copy of the comment will be sent to you via email.</span>
        <form id='comment-form-git-conflict-resolution-45770d783cfea6b30ec2a4a46a3481b5' action='/comment/git-conflict-resolution' method='post' class='comment-form'>
          <input type='text' name='email' id='textfield-email'/>
          <input type='submit' value='email me' id='submit-email me'/>
        <input type='hidden' name='comment-id' value='45770d783cfea6b30ec2a4a46a3481b5'/>
  <span class="form-result" id="form-result-git-conflict-resolution-45770d783cfea6b30ec2a4a46a3481b5"><!-- spanna --></span>
</form>

      </div>
    </div>
  </div>

  </li></ul></li>
  
</ul>

<p class="comment-instructions">To leave a new comment, enter your email
address. A copy of the article will be sent to you via email.</p>
<form id='comment-form-git-conflict-resolution' action='/comment/git-conflict-resolution' method='post' class='comment-form'>
  <input type='text' name='email' id='textfield-email'/>
  <input type='submit' value='email me' id='submit-email me'/>
  <span class="form-result" id="form-result-git-conflict-resolution"><!-- spanna --></span>
</form>


<script type="text/javascript">
/* <![CDATA[ */
$$('.comment-form').addEvent('submit', function(e) {
  e.stop();
  var el = this.getElement('.form-result');
  var result = el.empty().addClass('ajax-loading');
  this.set('send', {
    method: 'post',
    onComplete: function(response) { 
      result.removeClass('ajax-loading');
      result.set('html', response);
    },
  });
  this.send();
});
/* ]]> */
</script>


<script type="text/javascript">
/* <![CDATA[ */
$$('.reply-to-link').each(function(link, i) {
  var box = link.getParent().getParent().getElement('.reply-to-box');
  var oldHeight = box.getStyle("height");
  box.setStyle("height", 0);
  box.setStyle("opacity", 0);
  link.addEvent('click', function(e) {
    e.stop();
    box.setStyle("opacity", 1);
    box.setStyle("height", oldHeight);
    box.getElement("input").focus();
  });
});
/* ]]> */
</script>

  </div>

  <div id="footer" style="margin: 0px;">
    Served up by <a href="http://masanjin.net/whisper/">Whisper</a>. Yes!
  </div>
</div>
</body>
</html>
