{"id":186,"date":"2007-11-30T20:33:48","date_gmt":"2007-12-01T00:33:48","guid":{"rendered":"http:\/\/benjamin.smedbergs.us\/blog\/2007-11-30\/merging-with-mercurial-queues\/"},"modified":"2007-11-30T20:33:48","modified_gmt":"2007-12-01T00:33:48","slug":"merging-with-mercurial-queues","status":"publish","type":"post","link":"http:\/\/benjamin.smedbergs.us\/blog\/2007-11-30\/merging-with-mercurial-queues\/","title":{"rendered":"Merging with Mercurial Queues"},"content":{"rendered":"<p>I&#8217;ve spent most of the last 2.5 days merging code that lives in mercurial patch queues. It&#8217;s been an interesting (and frustrating) experience, but I&#8217;ve learned a lot, so I put together this tutorial on maintaining\/merging\/updating a mercurial patch queue.<\/p>\n<h3>The XPCOMGC patch queue<\/h3>\n<p>The XPCOMGC patch queue was actually 60+ patches long, but for example purposes let&#8217;s simplify to 7. What makes it tricky is that patches &#8220;after&#8221; the automated rewrites often won&#8217;t apply cleanly to the tree before the automatic rewrite. This means that moving patches from &#8220;after an automatic rewrite&#8221; to &#8220;before an automatic rewrite&#8221; requires a merge algorithm. Imagine a patch series like this:<\/p>\n<pre>manual-fixbugA\r\nmanual-fixbugB\r\nautomatic-rewrite-comptrs\r\nautomatic-rewrite-classhierarchy\r\nautomatic-rewrite-addrefs\r\nmanual-fixbugA-patch2\r\nmanual-fixbugC<\/pre>\n<p>You may be wondering about &#8220;manual-fixbugA-patch2&#8243;&#8230; why didn&#8217;t I just go back to manual-fixbugA and change it? This is because, once you&#8217;ve applied an automatic rewrite, popping\/editing\/pushing requires not only a complete tree rebuild (20 minutes), but also rebuilding the automated patches (hours). Instead, I create a &#8220;patch2&#8221; (and sometimes a &#8220;patch3&#8221; and &#8220;patch4&#8221;) and later fold the patches together.<\/p>\n<h3>Reordering a patch queue<\/h3>\n<p>I want to clean up this patch queue and update the &#8220;base tree&#8221; on which I&#8217;m applying patches. To do this, I&#8217;m first going to move all the &#8220;manual&#8221; patches before the automatic rewrites. Some of the patches may not apply cleanly in their new positions, so we prepare for merging. 64<\/p>\n<pre>$ hg qpush -a;          # Push all patches\r\n$ hg qsave -e -c;       # Save the patch queue state... this allows for merging later\r\n$ hg update -C qparent; # Move the working directory back to a completely unpatched state<\/pre>\n<p>Now we edit the <tt>.hg\/patches\/series<\/tt> file, removing the automatic rewrites. Instead of attempting to merge the automatic rewrites, we will simply regenerate them later.<\/p>\n<pre>manual-fixbugA\r\nmanual-fixbugB\r\nmanual-fixbugA-patch2\r\nmanual-fixbugC<\/pre>\n<p>Now we push the patches back on: if a patch doesn&#8217;t apply cleanly, use a three-way merge algorithm based on the saved patch queue state:<\/p>\n<pre>hg qpush -m; # applies manual-fixbugA\r\nhg qpush -m; # applies manual-fixbugB\r\nhg qpush -m; # applies manual-fixbugA-patch2 with interactive merging\r\nhg qpush -m; # applies manual-fixbugC with interactive merging<\/pre>\n<p>Now, we want to merge the changes from &#8220;manual-fixbugA-patch2&#8221; into &#8220;manual-fixbugA&#8221;<\/p>\n<pre>hg qgoto manual-fixbugA;\r\nhg qfold manual-fixbugA-patch2;<\/pre>\n<p>Now we have a clean patch queue which is ready for updating to a new &#8220;base&#8221;:<\/p>\n<pre>hg qpush -a;    # Push all patches in preparation for our second merge\r\nhg qsave -e -c; # Save the patch queue state (again)\r\nhg pull http:\/\/hg.mozilla.org\/actionmonkey; # Pull new changesets from actionmonkey\r\nhg up tip;      # Update the working directory to the unpatched actionmonkey tip\r\nhg qpush -m;    # merge the patches one by one, with merging if necessary<\/pre>\n<p>In the case of XPCOMGC, &#8220;new-base&#8221; merges are difficult primarily because of the cycle collector. Cycle-collection is still be actively developed on trunk, with major changes to the xpconnect mark\/trace algorithms as well as changes to timing. One of the earliest patches in the XPCOMGC queue removes cycle-collector entirely (when we have a garbage collector for XPCOM objects a cycle collector is no longer needed). Merge conflicts are common not only in the patch which removes the cycle collector, but in subsequent patches which touch xpconnect.<\/p>\n<p>I&#8217;ve learned that merging goes much better if every patch in the patch queue produces a building tree. To test whether a merge was performed correctly (or discover which patch was merged incorrectly), simply build the tree at each patch state.<\/p>\n<h3>Conclusion<\/h3>\n<p>Mercurial patch queues make it possible to merge-update a series of patches against a moving base, which is very cool. But they don&#8217;t remove the actual hard work of merging changes that conflict.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve spent most of the last 2.5 days merging code that lives in mercurial patch queues. It&#8217;s been an interesting (and frustrating) experience, but I&#8217;ve learned a lot, so I put together this tutorial on maintaining\/merging\/updating a mercurial patch queue. The XPCOMGC patch queue The XPCOMGC patch queue was actually 60+ patches long, but for [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[41,56,62,63],"class_list":["post-186","post","type-post","status-publish","format-standard","hentry","category-mozilla","tag-mercurial","tag-mozilla2","tag-mqueue","tag-xpcomgc"],"_links":{"self":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/comments?post=186"}],"version-history":[{"count":0,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/186\/revisions"}],"wp:attachment":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/media?parent=186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/categories?post=186"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/tags?post=186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}