| 32 | == Branching {{{im.pidgin.gaim}}} == |
| 33 | |
| 34 | There are two kinds of branches in monotone, which I will call ''macro-'' and ''micro-''branches. We will deal with each in turn. |
| 35 | |
| 36 | === macro-branches === |
| 37 | |
| 38 | A ''macro-branch'' is a set of monotone revisions which have a particular certificate associated with them, identifying them as belonging to the same branch. In our case, the "main" branch of development is {{{im.pidgin.gaim}}}. All revisions in the monotone database which carry a cert of type {{{branch}}} with the value {{{im.pidgin.gaim}}} are on this branch. Note that, technically, revisions on such a branch don't have to have any relation to one another -- however, it probably makes sense that they are all descended from some ultimate ancestor revision, and that they are logically related in some fashion. In the case of {{{im.pidgin.gaim}}}, they form a (presently) linear history taken from the Gaim svn repository. |
| 39 | |
| 40 | Branch certificates are a little bit "magic", in that monotone knows about them and changes its behavior based on them. For example, a {{{commit}}}ted revision will inherit the branch certificate of its parent. An {{{update}}} on a workspace will update to the "newest" (DAG-wise; more on this later) revision bearing the same branch tag. The set of revisions to synchronize via netsync is chosen by a branch specification pattern. |
| 41 | |
| 42 | Creating a new branch is as easy as committing a revision with a new branch name, or adding a new branch certificate to an existing revision. The former is accomplished at commit time by supplying the {{{-b}}} or {{{--branch}}} argument to {{{monotone commit}}}. The latter is accomplished with the command {{{mtn approve -b <branch-name> <revision>}}} or {{{mtn cert <revision> branch <branch-name>}}}. Branch names are not structured (that is to say, their structure is not ''enforced''), but good practices for branch naming suggest that related branches have similar names. BCP seems to be Java-style inverted-domain naming. |
| 43 | |
| 44 | Merging two branches is accomplished with the command {{{mtn propagate <from-branch> <to-branch>}}}. There are other ways to merge (''e.g.'', approve or cert a revision onto the destination branch, and then handle as a micro-branch below), but this is the most straightforward and will normally serve your purposes. |
| 45 | |
| 46 | === micro-branches === |
| 47 | |
| 48 | Every history in monotone is represented as a directed acyclic graph (DAG). This means that every revision checked into the database has an ''explicit'' list of parent revisions, which are fixed at the moment that the revision is committed and are thereforth immutable. The DAG structure is general; this means that a revision can have more than one parent (currently, I believe it is only possible to have zero, one, or two, due to the implementation of monotone), and more than one revision can have the same parent (that is to say, a revision can have more than one child). Because ancestors are immutable, and an ancestor must exist at creation time, a revision can never be its own ancestor -- thus the acyclic part. |
| 49 | |
| 50 | Due to the distributed nature of monotone, a little bit of thought will lead to the conclusion that it is possible to have a DAG which has more than one "head" revision. Consider the case where two developers pull from the {{{pidgin.im}}} repository at the same time, and thus receive the same head; let us call it {{{0123abcd}}}. Each developer goes on to make a change, and commits that change to their local database. Say, {{{a1b2c3d4}}} for {{{devA}}} and {{{9876fedc}}} for {{{devB}}}. The two developers then push their local changes to {{{pidgin.im}}}, and lo and behold, we have the graph: |
| 51 | |
| 52 | {{{ |
| 53 | ,--a1b2c3d4 |
| 54 | / |
| 55 | ... 0123abcd |
| 56 | \ |
| 57 | '--9876fedc |
| 58 | }}} |
| 59 | |
| 60 | We call {{{a1b2c3d4}}} and {{{9876fedc}}} the ''heads'' of the branch {{{im.pidgin.gaim}}}, and the heads of a branch can be viewed with the command {{{mtn heads}}}. I call this divergence (within the same logical branch {{{im.pidgin.gaim}}}) a ''micro-branch''. |
| 61 | |
| 62 | Such a micro-branch obviously cannot be resolved with {{{mtn propagate}}}, as both revisions are on the same logical branch. To resolve such a branch, the command {{{mtn merge}}} is used. Either {{{devA}}} or {{{devB}}} can merge these two revisions, say yielding a fourth revision {{{deadbeef}}}. The resulting graph then looks like: |
| 63 | |
| 64 | {{{ |
| 65 | ,--a1b2c3d4, |
| 66 | / \ |
| 67 | ... 0123abcd deadbeef |
| 68 | \ / |
| 69 | '--9876fedc' |
| 70 | }}} |
| 71 | |
| 72 | Given that such structure exists and is possible, it can be eploited intentionally as well as created inadvertently. Monotone:DaggyFixes discusses just this, and its usage in identifying and fixing bugs. Additionally, this means that it is not necessary (as it often is with svn and CVS) to update your working directory before committing pending changes; simply commit them at the point where you created them, and then merge this commit with the branch as it currently stands. |
| 73 | |
| 74 | Note that {{{mtn update}}} will not update a branch which has multiple heads; you will either have to explicitly {{{mtn update -r <revision>}}} to select a particular head (or other revision), or merge the divergent heads before updating. |
| 75 | |
| 76 | === Branch Complexity === |
| 77 | |
| 78 | While all of this seems somewhat complex and difficult compared to the linear-history model of CVS or svn, it is really quite unavoidable in the context of a distributed VCS (as the above example shows). Different systems handle it differently (darcs in particular using quite a different model), but the problem will exist in any such system. Once you get your head wrapped around it, it's actually quite intuitive and powerful. |
| 79 | |