{"id":1215,"date":"2011-01-26T19:59:55","date_gmt":"2011-01-27T00:59:55","guid":{"rendered":"http:\/\/unitstep.net\/?p=1215"},"modified":"2011-01-26T20:09:10","modified_gmt":"2011-01-27T01:09:10","slug":"folding-changesets-with-the-mercurial-queues-extension","status":"publish","type":"post","link":"https:\/\/unitstep.net\/blog\/2011\/01\/26\/folding-changesets-with-the-mercurial-queues-extension\/","title":{"rendered":"Folding changesets with the Mercurial Queues extension"},"content":{"rendered":"
<\/p>\n
Mercurial is my distributed revision control system of choice, a trait I picked up at my previous job. I haven’t had the opportunity to deal with Git for any period of time, so I can’t comment on the various “Why X is better than Y<\/a>” arguments<\/a> out there<\/a>. <\/p>\n Most of you using Mercurial\/Hg (or revision control in general) will be familiar with the concept of merging<\/em>, where the changes in a source branch are merged into a target branch, creating a new revision or changeset on the target branch. But what about the times when you would like to combine two or more changesets\/revisions into a single one that has the combined\/overall changes of all of them? In that case, the Mercurial Queues extension provides for the concept of folding<\/em>, which accomplishes just that.<\/p>\n <\/p>\n The Mercurial Queues extension<\/a> (mq<\/strong>) is one of the most useful Hg extensions available, as it allows for much more<\/a> than folding. Basically, mq allows you to import changesets to a patch queue<\/em>, where they can be manipulated. In this way, previously immutable changesets can be modified. One such modification is the concept of folding<\/em>, where one more more changesets are combined to produce a single changeset with the equivalent effect.<\/p>\n Because mq can directly modify changesets (i.e. revision history), it can have adverse on your Hg repository; data can be permanently lost, since the changes that can be made cannot be “backed out” or “reverted”. I strongly recommend cloning your Hg repo before undertaking any actions with Mercurial Queues for the first time<\/strong>, if only for peace of mind and the fact that cloning is such an easy operation with Mercurial.<\/p>\n Generally, it’s not a good idea to go and change revision history, which is what folding does. The purpose of revision control is to preserve<\/em> history and provide a timeline for how the codebase has evolved. In the case of Mercurial, it’s especially troublesome to go and modify revision history on a central server that others are pushing to\/pulling from, as this may cause inconsistencies. Having said that, there are times when combining multiple changesets into one may be beneficial.<\/p>\n Some examples that come to mind are:<\/p>\n Folding will help in both situations.<\/p>\n This tutorial will cover folding using TortoiseHg<\/a>, the popular GUI front-end for Mercurial. Before getting started, you’ll have to ensure that you don’t have any uncommitted changes, as you won’t be able to accomplish some of the steps with outstanding changes. <\/p>\n Open up the Repository Explorer. Below, you can see the example one, with our initial commit, which contained the sensitive data, followed by another that removed it. We’ll merge them into one.<\/p>\n \n Next, you’ll need to enable the Mercurial Queues extension, either through the TortoiseHg UI or by manually editing your \n You’ll need to close the Repository Explorer and re-open it for the mq extension to take effect in the UI. <\/p>\n Next, select the oldest<\/strong> changeset and then right-click the newest one<\/strong>; in the context menu, select “Import from here to selected MQ”.<\/p>\n \n Then, open the Patch Queue by clicking its icon or selecting View > Patch Queue<\/strong> from the menu.<\/p>\n \n You should be able to see the changesets in your patch queue on the left side drawer. They’ll be labeled 0.diff, 1.diff, etc. You can also see which patch corresponds to which changeset because the imported changesets will have be labeled in the UI with qbase, qtip, 0.diff, 1.diff<\/strong>, etc. (They are listed in the patch queue in opposite order)<\/p>\n \n Now, right-click the top\/oldest one<\/strong> in the patch queue, and select “Goto”. This will bring you back to the oldest changeset and remove<\/strong> the previous ones from your repository. But don’t worry, the changesets still exist in your (mercurial) queue.<\/p>\n \n Now, right click the next oldest one (which was removed from your repository), click “Fold” and then “Yes”. This will effectively fold or combine the two changesets into a single one with the equivalent changes\/effects. Please note that this operation cannot be reversed<\/strong>, so make sure you really want to do it. (You did clone\/backup your repository before starting, right?)<\/p>\n \n \n You can now adjust the commit comment\/message and username, if you like, by clicking “Commit” or by selecting Tools > Commit<\/strong> from the menu. You may need to select View > Advanced<\/strong> to change\/show the username. By default the commit message of the folded\/unified changeset is an aggregate of the changesets that were combined to form it. You’ll probably want to adjust this down to something more meaningful. <\/p>\n After you are done, be sure to click “QRefresh”<\/strong> before closing the window.<\/p>\n \n After you’ve done the folding and modifying the commit message, you can right click the patch file (0.diff in this case) and select “Finish Applied” to put the folded\/unified changeset back into your repository.<\/p>\nMercurial Queues<\/h2>\n
Proceed with caution<\/h2>\n
The case for folding<\/h2>\n
\n
Tutorial<\/h2>\n
<\/a>\n<\/p>\n
mercurial.ini<\/code> file or per-repo setting file. (
.hgrc<\/code>) Below, I’ve shown it in the UI: You need to check off the “mq” box under “Extensions”<\/strong>.<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n
<\/a>\n<\/p>\n