Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing release branches in Mercurial

Recently I switched from SVN to Mercurial. Now I wonder how to realize my intended branching work flow in Mercurial according to good practice, hoping other developers understand what happens in the repository.

This is the work flow:

  1. Usually I have a trunk/default branch where work on the current release series happens. Let's say that is 1.x. At the same time I use a branch 2.x to work on the next major release. Changes in this branch may be radical, so merging with the trunk/default/1.x branch makes no sense here.
    • After a while work on 2.x may be finished and version 2.0 gets released. Now I want the 2.x branch to be the new default/trunk branch and the current default/trunk to be the 1.x branch.
    • Repeating this process, there may come a new 3.x branch. As before, if 3.0 gets released, 3.x should become the new default branch while the then current default should become the 2.x branch (again).

My question is not whether this work flow is a good one (I guess it's not fundamentally wrong). My questions is whether the way I realize this in Mercurial can be seen as good practice or if there are better opportunities.

So here is how I plan to manage branches in Mercurial ...

Starting from a repository with a single branch which holds the code of the current release series 1.x:

$ hg init
$ echo "hello world" > file1.txt
$ hg ci -A -m "Initial commit of 1.x code"

Start working on release 2.x:

$ hg branch 2.x
$ hg ci -m "Create new branch for 2.x development"
$ echo "Big new feature for 2.x" > file2.txt
$ hg ci -A -m "Add big new feature"

Meanwhile, do some work in current release series (1.x):

$ hg up default
$ echo "Minor adjustments specific for 1.x" > file3.txt
$ hg ci -A -m "Minor adjustments"

After some time release 2.0 is ready, yippee! Make default branch to 1.x and 2.x to default:

$ hg up default
$ hg branch 1.x
$ hg ci -m "Make default branch to 1.x branch"
$ hg up 2.x
$ hg ci --close-branch -m "Close branch 2.x"
$ hg branch --force default
$ hg ci -m "Make former 2.x branch to new default"

Now create a new branch 3.x and work in it, also work on default. Again, after some time 3.0 is ready and it's time again to manage branch names:

$ hg up default
$ hg branch --force 2.x # (reuse previously closed 2.x branch name)
$ hg ci -m "Make default branch to 2.x branch"
$ hg up 3.x
$ hg ci --close-branch -m "Close branch 3.x"
$ hg branch --force default
$ hg ci -m "Make former 3.x branch to new default"

The repo now may look like this ('o' are the heads):

o Branch default (3.x)
|
| o Branch 2.x
 \|
  | o Branch 1.x
   \|
    |
    .

The main point I'm not sure about is if reusing branch names and juggling with the branch name default is good practice.

A lot of text for that question - sorry - but I wanted to be clear about what I'm doing.

like image 962
Oben Sonne Avatar asked Sep 10 '09 14:09

Oben Sonne


People also ask

How do you remove a tag on Mercurial?

If you want to remove a tag that you no longer want, use hg tag --remove . You can also modify a tag at any time, so that it identifies a different revision, by simply issuing a new hg tag command. You'll have to use the -f option to tell Mercurial that you really want to update the tag.

What is a branch in Mercurial?

Branches occur if lines of development diverge. The term "branch" may thus refer to a "diverged line of development". For Mercurial, a "line of development" is a linear sequence of consecutive changesets. Combining a line of development into an existing one is called merging. Creating a branch.

How do you tag in Mercurial?

To add a tag to the system, simply add a line to this file and then commit it for it to take effect. The hg tag command will do this for you and hg tags will show the currently effective tags.


2 Answers

Here's what I'd do:

Make default your "mainline" branch. The tip of this branch is the "currently released to the public" version of your code. Critical bugfixes can be committed directly to this branch and merged into development branches.

To start working on version 2.0, make a 2.0-dev branch. Commit changes for 2.0 to that branch, and merge critical bugfixes from the mainline (default) into it. Once you're done with 2.0, merge 2.0-dev into default and tag the result as 2.0.

Doing things this way means you don't have to worry about juggling branch names, and you can merge critical bugfixes to the mainline into development branches quite easily.

It also scales well when you're working on multiple future versions at once (say 2.1 and 3.0). You can periodically merge the 2.1 changes into 3.0 to keep 3.0 current.

You'll end up with a graph like this:

$ hg glog -l 1000 @       changeset:  25:efc0096f47c0  tip |       summary:    Added tag 3.0 for changeset d1a7fc3d7d77 | o       changeset:  24:d1a7fc3d7d77  3.0 |\      summary:    Merge in the redesign changes. | | | o     changeset:  23:b5b69d24c8f7 3.0-dev | |     summary:    Finish 3.0 redesign. | | | o     changeset:  22:4c2f98fac54b 3.0-dev |/|     summary:    Merge in the latest changes to 2.1/mainline. | | o |     changeset:  21:37df04521032 | |     summary:    Added tag 2.1 for changeset 39ecc520fc0a | | o |     changeset:  20:39ecc520fc0a  2.1 |\ \    summary:    2.1 development is done. | | | | o |   changeset:  19:208f3f9236af 2.1-dev | | |   summary:    Finish the 2.1 work. | | | | | o   changeset:  18:4a024009a9d6 3.0-dev | | |   summary:    More redesign work. | | | | | o   changeset:  17:00c416888c25 3.0-dev | |/|   summary:    Merge in changes from the 2.1 branch to keep the redesign current. | | | | o |   changeset:  16:a57e781a0db1 2.1-dev | | |   summary:    More 2.1 work. | | | | | o   changeset:  15:ddeb65402a61 3.0-dev | | |   summary:    More redesign work. | | | +---o   changeset:  14:90f5d7a8af9a 3.0-dev | | |   summary:    Merge in the fire fixes. | | | | o |   changeset:  13:78a949b67bb9 2.1-dev |/| |   summary:    Merge in the fire fixes. | | | o | |   changeset:  12:6dfe9d856202 | | |   summary:    Oh no everything is on fire, fix it in the mainline. | | | | o |   changeset:  11:86767671dcdb 2.1-dev | | |   summary:    Smaller changes for 2.1. | | | | | o   changeset:  10:25dec81d2546 3.0-dev | | |   summary:    Work more on the redesign. | | | +---o   changeset:  9:42c7d689fb24 3.0-dev | |     summary:    Start working on a complete redesign. | | | o     changeset:  8:3da99186ca7d 2.1-dev |/      summary:    Start working on 2.1. | o       changeset:  7:9ba79361827d |       summary:    Added tag 2.0 for changeset 755ed5c5e291 | o       changeset:  6:755ed5c5e291  2.0 |\      summary:    Merge in the dev branch for 2.0. | | | o     changeset:  5:44a833fcc838 2.0-dev | |     summary:    Finish work on 2.0. | | | o     changeset:  4:d7ba6aae1651 2.0-dev |/|     summary:    Merge in the critical fix. | | o |     changeset:  3:968049f1b33a | |     summary:    Fix a critical bug on the main branch. | | | o     changeset:  2:917869609b25 2.0-dev | |     summary:    More work on the new version. | | | o     changeset:  1:f95798b9cb2e 2.0-dev |/      summary:    Start working on version 2.0. | o       changeset:  0:8a3fb044d3f4         summary:    Initial commit. 
like image 199
Steve Losh Avatar answered Oct 13 '22 21:10

Steve Losh


I think you should consider this: a successfull git branching model.

I am not the big fan of git, but this model is extra usefull for mercurial too.

like image 41
Alex Povar Avatar answered Oct 13 '22 19:10

Alex Povar