Update (2013-04-18): In #mercurial @ irc.freenode.net there were discussions yesterday for improving the help output if you do not have your username setup, yet.
I recently tried contributing to a new project again, and I was quite surprised which hurdles can be in your way, when you did not setup your environment, yet.
So I decided to put together a small test for the basic workflow: Cloning a project, doing and testing a change and pushing it back.
I did that for Git and Mercurial, because both break at different points.
I’ll express the basic usecase in Subversion:
You can also replace the request for commit rights with creating a patch and sending it to a mailing list. But let’s take the easiest case of a new contributor who is directly welcomed into the project as trusted committer.
A slightly more advanced workflow adds testing in a clean tree. In Subversion it looks almost like the simple commit:
Currently I rework my code extensively before I push it into upstream SVN. Some of that is inconvenient and it would be nicer to have easy to use refactoring tools.
hg evolve might offer that.
This test uses the mutable-hg extension in revision c70a1091e0d8 (24 changesets after 2.1.0). It will likely be obsolete, soon, since mutable-hg is currently moved into Mercurial core by Pierre-Yves David, its main developer. I hope it will be useful for you, to assess the future possibilities of Mercurial today. This is not (only) a pun on “obsolete”, the functionality at the core of evolve which allows safe, collaborative history rewriting ☺
This is a complete branching strategy for Mercurial with optional adaptions for maintaining multiple releases1. It shows you all the actions you may need to take, except for those already described in the guide Mercurial in workflows.
For examples it uses the command-line UI, but it can easily be used with graphical Mercurial interfaces like TortoiseHG, too.
Firstoff, any model to be used by people should boil down to simple rules. Programming is complex enough without having to worry about elaborate branching rules. This model uses 3 simple rules:
(1) you do all the work on
default2 - except for hotfixes.
(3) you can use arbitrary feature-branches5, as long as you don’t call them
stable. They always start at default (since you do all the work on default).
To visualize the structure, here’s a 3-tiered diagram. To the left are the actions of developers (commits and feature branches) and in the center the tasks for maintainers (release and hotfix). The users to the right just use the stable branch.6
Now we can look at all the actions you will ever need to do in this model:7
Initialize (only needed once)
create the repo:
hg init reponame; cd reponame
(edit); hg ci -m "message"
create the stable branch and do the first release:
hg branch stable; hg tag tagname; hg up default; hg merge stable; hg ci -m "merge stable into default: ready for more development"
(edit); hg ci -m "message"
continue development after a release:
hg update; (edit); hg ci -m "message"
start a larger feature:
hg branch feature-x; (edit); hg ci -m "message"
continue with the feature:
hg update feature-x; (edit); hg ci -m "message"
merge the feature:
hg update default; hg merge feature-x; hg ci -m "merged feature x into default"
close and merge the feature when you are done:
hg update feature-x; hg ci --close-branch -m "finished feature x"; hg update default; hg merge feature-x; hg ci -m "merged finished feature x into default"
Tasks for Maintainers
apply a hotfix8:
hg up stable; (edit); hg ci -m "message"; hg up default; hg merge stable; hg ci -m "merge stable into default: ready for more development"
do a release9:
hg up stable; hg merge default; hg ci -m "merged default into stable for release" ; hg tag tagname; hg up default ; hg merge stable ; hg ci -m "merged stable into default: ready for more development"
default is the default branch. That’s the named branch you use when you don’t explicitely set a branch. Its alias is the empty string, so if no branch is shown in the log (
hg log), you’re on the default branch. Thanks to John for asking! ↩
If you want to release the changes from
default in smaller chunks, you can also graft specific changes into a release preparation branch and merge that instead of directly merging default into stable. This can be useful to get real-life testing of the distinct parts. For details see the extension Graft changes into micro-releases. ↩
Maintainers are those who do releases, while they do a release. At any other time, they follow the same patterns as everyone else. If the release tasks seem a bit long, keep in mind that you only need them when you do the release. Their goal is to make regular development as easy as possible, so you can tell your non-releasing colleagues “just work on default and everything will be fine”. ↩
This model does not use bookmarks, because they don’t offer benefits which outweight the cost of introducing another concept, and because named branches for feature branches offer the advantage, that new programmers never get the code from a feature-branch when they clone the repository. For local work and small features, bookmarks can be used quite well, though, and since this model does not define their use, it also does not limit it.
Additionally bookmarks could be useful for feature branches, if you use many of them (in that case reusing names is a real danger and not just a rare annoyance, and if you have a recent Mercurial, you can use the
@ bookmark to signify the entry point for new clones) or if you use release branches:
“What are people working on right now?” →
“Which lines of development do we have in the project?” →
hg branches ↩
Those users who want external verification can restrict themselves to the tagged releases - potentially GPG signed by trusted 3rd-party reviewers. GPG signatures are treated like hotfixes: reviewers sign on stable (via
hg sign without options) and merge into default. Signing directly on stable reduces the possibility of signing the wrong revision. ↩
hg pull and
hg push to transfer changes and
hg merge when you have multiple heads on one branch are implied in the actions: you can use any kind of repository structure and synchronization scheme. The practical actions only assume that you synchronize your repositories with the other contributors at some point. ↩
Here a hotfix is defined as a fix which must be applied quickly out-of-order, for example to fix a security hole. It prompts a bugfix-release which only contains already stable and tested changes plus the hotfix. ↩
If your project needs a certain release preparation phase (like translations), then you can simply assign a task branch. Instead of merging to stable, you merge to the task branch, and once the task is done, you merge the task branch to stable. An Example: Assume that you need to update translations before you release anything. (next part: init: you only need this once) When you want to do the first release which needs to be translated, you update to the revision from which you want to make the release and create the “translation” branch:
hg update default; hg branch translation; hg commit -m "prepared the translation branch". All translators now update to the translation branch and do the translations. Then you merge it into stable:
hg update stable; hg merge translation; hg ci -m "merged translated source for release". After the release you merge stable back into default as usual. (regular releases) If you want to start translating the next time, you just merge the revision to release into the translation branch:
hg update translation; hg merge default; hg commit -m "prepared translation branch". Afterwards you merge “translation” into stable and proceed as usual. ↩
If you want to adapt the model to multiple very distinct releases, simply add multiple release-branches (i.e.
hg graft the changes you want to use from default or stable into the releases and merge the releases into stable to ensure that the relationship of their changes to current changes is clear, recorded and will be applied automatically by Mercurial in future merges11. If you use multiple tagged releases, you need to merge the releases into each other in order - starting from the oldest and finishing by merging the most recent one into stable - to record the same information as with release branches. Additionally it is considered impolite to other developers to keep multiple heads in one branch, because with multiple heads other developers do not know the canonical tip of the branch which they should use to make their changes - or in case of stable, which head they should merge to for preparing the next release. That’s why you are likely better off creating a branch per release, if you want to maintain many very different releases for a long time. If you only use tags on stable for releases, you need one merge per maintained release to create a bugfix version of one old release. By adding release branches, you reduce that overhead to one single merge to stable per affected release by stating clearly, that changes to old versions should never affect new versions, except if those changes are explicitely merged into the new versions. If the bugfix affects all releases, release branches require two times as many actions as tagged releases, though: You need to graft the bugfix into every release and merge the release into stable.12 ↩
If for example you want to ignore that change to an old release for new releases, you simply merge the old release into stable and use
hg revert --all -r stable before committing the merge. ↩
A rule of thumb for deciding between tagged releases and release branches is: If you only have a few releases you maintain at the same time, use tagged releases. If you expect that most bugfixes will apply to all releases, starting with some old release, just use tagged releases. If bugfixes will only apply to one release and the current development, use tagged releases and merge hotfixes only to stable. If most bugfixes will only apply to one release and not to the current development, use release branches. ↩
In the mercurial list Stanimir Stamenkov asked how to get rid of intermediate merges in the log to simplify reading the history (and to not care about missing some of the details).
Update: Since Mercurial 2.4 you can simply use
hg log -Gr "branchpoint()"
I did some tests for that and I think the nicest representation I found is this:
hg log -Gr "(all() - merge()) or head()"
then this workflow might be right for you.
Note: If you have a huge number of small features (2000 and upwards), the number of persistent named branches can create certain performance problems. For features which need no collaboration or need only a few commits, this workflow also has much unnecessary overhead. It is best used for features which will be developed side by side with default for some time (and many commits), so tracking the default branch against the feature is relevant. To mark single-commit features as belonging to a feature, just use the commit message.
Note: The difference between Mercurial named branches and git branches is that git branches don’t stay in history. They don’t allow you to find out later in which branch a certain commit was added. If you want git-style branching, just use bookmarks.
It delves into nonlinear history and merging right from the beginning and uses only features you get without activating extensions. Due to this it offers efficient and safe workflows without danger of losing already committed work.
Anonymous DVCS in the Darknet.
This is a mirror of the documentation of the infocalypse extension for Mercurial written by djk - published here with his permission. It is licensed solely under the GPLv2 or later.
Your code is then hosted decentrally and anonymously, making it just as censorship-resistant as all other content in Freenet.
It works better than the other DVCS currently available for Freenet.
Most of the information you will find in this document can also be found in the extension's online help. i.e.:
hg help infocalypse
If you want to publish your scientific scripts, as Nick Barnes advises in Nature, you can very easily do so with Mercurial.
All my stuff (not just code), excempting only huge datasets, is in a Mercurial source repository1.
Whenever I change something and it does anything new, I commit the files with a simple commit (even if it’s only “it compiles!”).
→ comment to The next wave in scholarly word processors?
What I’d like to see is more people using version tracking systems.
With these you have a discussion which can be merged easily when it gets branched. I use it for anything I do, and I could use it together with an only-windows-and-GUI user with ease, installing TortoiseHG for both and Lyx for him (LaTeX made easy – you don’t have to see the sources).
What I miss in the internet is the notion of being able to control what my apps access for data.
Why can’t a chat application just connect to a neighborhood- or community-server, and why can’t the activity-stream come from the people I know — and query only their systems, like jabber does?
Almost all geolocation services should be implementable over direct friend-to-friend connections like jabber, and I don’t really see why my local identi.ca program can’t also get the news from my local jabber contacts.
Diese Seite nutzt Drupal.
Design: Arne Babenhauserheide.
Werke von Arne Babenhauserheide.
Lizensiert unter freien Lizenzen.