== Attic Extension == '''This extension is not distributed with Mercurial.''' ''Author: Bill Barry (BillBarry)'' Repository: https://bitbucket.org/Bill_Barry/hgattic Mailing list: http://groups.google.com/group/hgattic === Overview === This module deals with a set of patches in the folder .hg/attic. At any time you can shelve your current working copy changes there or unshelve a patch from the folder. === Configuration === Enable the extension by adding following lines to your configuration file (hgrc): {{{ [extensions] hgattic=/path/to/attic.py }}} === Usage === The extension adds a couple of commands, all starting with attic- so that they are grouped together in hg help, but all have shorter aliases: ==== hg attic-shelve ==== Shelve will take the current changes to the working copy and create a patch in the attic: {{{ hg shelve [name] }}} You need to supply a name for the patch when you first shelve it, but you can forget it if you are already working on a patch as, in that case, changes are added to the current patch. This command comes with a lot of options, some are: ||{{{-m}}} or {{{--message}}} || Use as the commit message || ||{{{-e}}} or {{{--edit}}} || Bring up an editor to supply the commit message || ||{{{-r}}} or {{{--refresh}}} || Refresh the current patch without stowing it away || ||{{{-i}}} or {{{--interactive}}} || Use the 'record' extension to interactively select hunks for a shelf || as well as some for setting the user and the date. See the command help for more details. ==== hg attic-unshelve ==== Unshelve is the mirrored partner to shelve {{{ hg unshelve [name] }}} (if any HUNK gets rejected because, for example, somebody else made changes to your files, you can consider using mpatch http://oss.oracle.com/~mason/mpatch/ to handle rejected files) You need to supply a name if it isn't the same as the last patch you were working on. Ex: {{{ ... do some work hg shelve patch1 ... fix a bug hg ci -m "fixed bug" hg unshelve ... name is not needed here because it is assumed to be patch1 }}} vs. {{{ ... do some work hg shelve patch1 ... work on something else hg shelve patch2 ... switch back to patch1 hg unshelve patch1 ... name is needed here because it is assumed to be patch2 }}} ==== hg attic-display ==== The attic command displays the list of patches in the attic: {{{ hg attic }}} There are some options to change what it displays: ||{{{-c}}} or {{{--current}}} || Show information about the current shelf being worked on || ||{{{-d}}} or {{{--header}}} || Show information about a given patch by name || === Comparison with similar functionality === Attic is much like several other extensions, but still is different enough that you have a reason to choose one above the other. ==== Mq ==== Attic and mq are alike in that: 1. They both deal with patches and you can use patches from one wherever you can use patches from the other. 2. Both are designed to enable sharing patches. Yet, these two extensions are very different. Mq is designed to work with a series of patches and attic is designed to work with a set of patches. If for example you have 3 patches that have nothing to do with each other in your series file in mq: {{{ feature1 feature2 feature3 }}} and you find that you are working on feature1 and suddenly realize there is a bug in feature2, you would: {{{ hg qpush ... working on feature1 and realize bug hg qrefresh hg qpop ... reorder feature2 and feature1 (put feature2 first) hg qpush ... fix feature2 hg qrefresh hg qpop ... reorder feature2 and feature1 (put feature1 first) hg qpush ... continue working on feature1 }}} whereas with attic: {{{ hg unshelve feature1 ... working on feature1 and realize bug hg shelve hg unshelve feature2 ... fix feature2 hg shelve hg unshelve feature1 ... go back to feature1 }}} While this process is workable in mq with only 3 patches, it grows unwieldly as your patch count increases. In addition to providing different usecases to mq, attic works well alongside mq, for example: splitting a patch in mq (one way of many): {{{ hg qgoto patchtosplit hg qpop ... move patchtosplit from .hg\patches to .hg\attic and remove it from series hg unshelve patchtosplit hg shelve -f --interactive patch1 hg shelve --interactive patch2 hg shelve therest hg unshelve --delete patchtosplit hg up -C qtip hg qimport .hg\attic\patch1 hg qimport .hg\attic\patch2 hg qimport .hg\attic\therest }}} working on feature1 and realize a fix for feature3, but you aren't ready to switch to it yet: {{{ hg qpush ... work on feature1, realize fix for feature3 hg qrefresh ... make fix for feature3 hg shelve feature3-fix ... continue on feature1, eventually doing hg qrefresh hg qgoto feature3 hg unshelve --delete feature3-fix ... now test the changes and qrefresh }}} see also MqExtension ==== Pbranch ==== Though I (BillBarry) do not know enough about pbranch yet to provide an in depth discussion on it, I do know enough to say that pbranch can do just about everything that attic can do (perhaps interactive shelving is the only thing attic can do that pbranch cannot) and can also be used to provide long term support for patches (attic is designed for mostly quick and dirty stuff). Pbranch is more powerful than attic in multiple ways (one quick example: pbranch can deal with a full patch graph whereas attic only deals with one patch at a time). However, with the power of pbranch comes the complexity of pbranch. see also PatchBranchExtension ==== Shelve ==== Shelve (the interactive shelving extension) is almost entirely a subset of attic. In fact attic's {{{hg shelve --interactive}}} is calling 3 methods directly pulled from the hgshelve extension source code. see also ShelveExtension === Potential usecases === temporarily shelving something away to fix something else: {{{ ... working on something, bug comes in hg shelve mywork ... make fix hg ci -m "fixed bug" hg unshelve ... continue }}} splitting patches: {{{ ... put bigpatch into .hg/attic hg unshelve bigpatch hg shelve -f --interactive patch1 hg shelve --interactive patch2 hg shelve finalpatch }}} cherry picking: {{{ all devs have attic under version control and 1 dev can pull from them: dev1 finishes feature: hg shelve -m "the message I want for the commit" -u featurea cd .hg/attic hg addrem hg ci -m "featurea ready" hg push (or whatever to make the patch public, example with shared repo assumed) dev2 finishes feature: hg shelve -m "the message I want for the commit" -u featureb cd .hg/attic hg addrem hg ci -m "featureb ready" hg push picker: cd .hg/attic hg pull cd ../.. hg unshelve featurea ... checks, it is ok hg ci (or move to mq, etc) hg unshelve featureb ... not ok hg shelve cd .hg/attic hg rm featurea hg ci -m "brought featurea into mainline" hg push }}} folding patches: {{{ ... patch1, patch2 and patch3 in attic hg unshelve --delete patch1 hg unshelve --delete -f patch2 hg unshelve --delete -f patch3 hg shelve foldedpatch }}} considering multiple implementations: {{{ ... do implementation 1 hg shelve impl1 ... do implementation 2 hg shelve impl2 ... do implementation 3 hg shelve impl3 ... converse with people about which patch is best hg unshelve impl2 hg ci -m "impl2 was best" cd .hg/attic rm impl1 rm impl3 }}} === Technical details === ==== Restrictions on patches ==== Don't create a patch with a name that starts with a period. It will not be shown with the attic-display command (and it could conflict with special files in the attic). Any special file in the attic is expected to start with a period (this is reserved for future usage as well). ==== Versioning the attic directory ==== You can put the attic under revision control, just ignore files that start with a period. This is particularly useful for sharing patches with a group of people. ==== Special files ==== Currently there are two special files: || .applied || contains the name of the current applied patch || || .current || contains the name of the assumed default patch || === See also === ShelveExtension, PatchBranchExtension, MqExtension ---- CategoryExtensionsByOthers