So by now you’re familiar with making changes, sharing them with other
people, and integrating your changes with their changes. Sometimes,
though, you may want to make some changes, and not integrate them
with other people’s — or at least not right away. One way to do this
would be to simply never run
mtn merge; but it would
quickly become confusing to try and keep track of which changes were in
which revisions. This is where branches are useful.
Continuing our example, suppose that Jim is so impressed by Beth’s work on banana juice support that he assigns her to work on the JuiceBot 7’s surprise new feature: muffins. In the mean time, Abe will continue working on the JuiceBot’s basic juice-related functions.
The changes required to support muffins are somewhat complicated, and Beth is worried that her work might destabilize the program, and interfere with Abe’s work. In fact, she isn’t even sure her first attempt will turn out to be the right approach; she might work on it for a while and then decide it was a bad idea, and should be discarded. For all these reasons, she decides that she will work on a branch, and then once she is satisfied with the new code, she will merge back onto the mainline.
She decides that since main development is in branch
jp.co.juicebot.jb7, she will use branch
jp.co.juicebot.jb7.muffins. So, she makes the first few edits to
the new muffins code, and commits it on a new branch by simply passing
--branch to commit:
$ mtn commit --branch=jp.co.juicebot.jb7.muffins --message='autobake framework' mtn: beginning commit on branch 'jp.co.juicebot.jb7.muffins' mtn: committed revision d33caefd61823ecbb605c39ffb84705dec449857
Alternately, she could not specify a message on the command line, and edit the “Branch” field in the changelog editor.
That’s all there is to it — there is now a
jp.co.juicebot.jb7.muffins branch, with her initial checkin on
it. She can make further checkins from the same workspace, and they
will automatically go to the muffins branch; if anyone else wants to
help her work on muffins, they can check out that branch as usual.
Of course, while Beth is working on the new muffins code, Abe is still
making fixes to the main line. Occasionally, Beth wants to integrate
his latest work into the muffins branch, so that her version doesn’t
fall too far behind. She does this by using the
$ mtn propagate jp.co.juicebot.jb7 jp.co.juicebot.jb7.muffins mtn: propagating jp.co.juicebot.jb7 -> jp.co.juicebot.jb7.muffins mtn: [source] da003f115752ac6e4750b89aaca9dbba178ac80c mtn: [target] d0e5c93bb61e5fd25a0dadf41426f209b73f40af mtn: common ancestor 853b8c7ac5689181d4b958504adfb5d07fd959ab email@example.com 2004-10-26T:12:44:23 found mtn: trying 3-way merge mtn: [merged] 89585b3c5e51a5a75f5d1a05dda859c5b7dde52f
propagate merges all of the new changes on one branch onto
When the muffins code is eventually stable and ready to be integrated into the main line of development, she simply propagates the other way:
$ mtn propagate jp.co.juicebot.jb7.muffins jp.co.juicebot.jb7 mtn: propagating jp.co.juicebot.jb7.muffins -> jp.co.juicebot.jb7 mtn: [source] 4e48e2c9a3d2ca8a708cb0cc545700544efb5021 mtn: [target] bd29b2bfd07644ab370f50e0d68f26dcfd3bb4af mtn: common ancestor 652b1035343281a0d2a5de79919f9a31a30c9028 firstname.lastname@example.org 2004-10-26T:15:25:05 found mtn: [merged] 03f7495b51cc70b76872ed019d19dee1b73e89b6
Monotone always records the full history of all merges, and is designed to handle an arbitrarily complicated graph of changes. You can make a branch, then branch off from that branch, propagate changes between arbitrary branches, and so on; monotone will track all of it, and do something sensible for each merge. Of course, it is still probably a good idea to come up with some organization of branches and a plan for which should be merged to which other ones. Monotone may keep track of graphs of arbitrary complexity — but you will have more trouble. Whatever arrangement of branches you come up with, though, monotone should be able to handle it.
If you are unsure of the name of a branch, you can list all branches using
ls branches command. This is very useful, but if you create
a lot of branches then the list can become very long and unwieldy. To help
this monotone has the
suspend command which partially hides
revisions/branches you are no longer using. Further commits on hidden branches
will automatically unhide the branches.
For example, if Beth is now finished with the muffins branch, she can stop it from cluttering the list of branches by suspending the last revision in that branch:
$ mtn ls branches jp.co.juicebot.jb7 jp.co.juicebot.jb7.muffins $ mtn heads mtn: branch 'jp.co.juicebot.jb7.muffins' is currently merged: 4e48e2c9a3d2ca8a708cb0cc545700544efb5021 email@example.com 2007-07-08T02:17:37 $ mtn suspend 4e48e2c9a3d2ca8a708cb0cc545700544efb5021 $ mtn ls branches jp.co.juicebot.jb7