Motivation
Why yet another version control system?
I like to commit when functionality is ready: each commit keeps repository functional.
I can still have my private branch ( what I do any way ), but even then on each step
i prefer to commit and revert changes if they went to dead end. Since we are using central
SVN repository ( same philosophy as CVS ) this approach is hard to achieve.
Mercurial allows to run two version control system in parallel - SVN for pushing/pulling changes from central repository
and mercurial for tracking local changes. This approach allow to commit into SVN final working code and keep all playing staff local.
Just Yet another toy to play :) .
Why not Git?
Mercurial has more SVN like command set, which will make learning process bit shorter. The main goal is the new concept which is hard enough. Once we hit Mercurial limitation we can switch ( oh my....).
How to Use Mercurial ( for dCache development ) on top of SVN
- Checkout from SVN
$ svn co svn+ssh://svn.dache.org/store/dCache dCache
- initialize Mercurial
$ cd dCache $ hg init $ cat > .hgignore <<EOF .svn/ .hgignore$ build/ dist/ .classpath$ .project$ EOF $ hg ci -Am "import sources into mercurial"
- edit ediT EDIT EDIT Edit edit
- modify code and commit changes into mercurial
$ hg commit
- produce patch series for review:
hg export -o ~/hp/%b-r\%r %n#%N.patch 0:tip
where 0:tip is a begin and end revisions numbers ( tip is the name of the HEAD revision )
- as soon as functionality is there commit changes into SVN
$ svn commit
How to Use plain Mercurial ( for dCache development and not only )
- Clone dCache repository ( ~900MB )
$ hg clone http://www.dcache.org/hg/dcache-hg dCache-hg
- edit ediT EDIT EDIT Edit edit
- modify code and commit changes into mercurial
$ hg commit
- produce patch series for review:
hg export -o ~/hp/%b-r\%r %n#%N.patch 0:tip
- send patch to <patch at dcache dot org>
The most scary part of any VCS (and DVCS even more) is the merge.
- get changes from central repository:
hg pull
this will pull changes from remote repository but will not update your working directory!
- update your woking directory
hg update
if you are lucky, then you are done. But very often you have to merge:
- merge
hg merge
if there is no conflicts, mercurial will merge changes and you will need to commit into your local repository your 'merged' changes.
In case of mercurial failed to merge, you have to resolve conflicts by hand.
Howto do patchwork
You concentrate your self on some new functionality or fix, but have to switch to something new. Your uncommited changes laying around and probably even do not compile. Typical solution - fresh checkout ( yet another 400MB ). Mercurial way to do it:
#1 hg qinit # initiates patch queue. need to do it only once #2 hg qnew <patch name> # start a new patch work e.g. hg qnew pnfs-speedup.patch #3 vi ... # hack hack hack #4 hg qrefresh # safe current state of the patch e.g in file .hg/patches/pnfs-speedup.patch #5 hg qpop pnfs-speedup.patch # remove patch from code #6 hg qpush pnfs-speedup.patch # apply patch
Patches can be grouped according functionality or version or...
hg qguard pnfs-speedup.patch +pnfs
Use only one set of patches
hg qselect pnfs
Push all patched from pnfs group
hg qselect pnfs hg qpush -a
Howto manage patches for two ( or more ) branches
Mercurial Queues have nice feature guards. The guards is a symbolic label to a set of patches. By choosing a guard you enable or disable patch group. By default, if no guard is selected, only unguarded patches apply.
I do have a separate repository for my patches:
$ mkdir myPaches $ cd myPatches $ hg init
clone dCache repository ( on any other ) and add patches to it:
$ hg clone http://..../dCache $ cd dCache/.hg $ hg clone /patch/to/myPatches patches $ cd ..
Now on you MQ is a mercurial repository itself. At any point you may do hg qcommit to commit your changes. If you work on several branches ( or if you use the same patch repository multiple projects ) at some point you will have patches which you want to exclude from your current 'working set'. The solution is guards :
$ hg gquard some-fix-for-a-branch.patch +myBranch $ hg qguard some-work-on-trunk.patch +trunk
depending which set you want to use you may enable one or the other set
$ hg qselect trunk $ hg qpush -a
only patches which have selected guard and all unguarded patches will apply
# real life example with my patches: $ hg qapplied $ $ hg qselect nfs $ hg qpush fix-nfs4-mover.patch applying junit-test-for-chimera-provider.patch skipping 1-9-0-build.patch - guarded by ['+19'] applying pnfs-hadler-cache.patch skipping chimera-pnfs-prodider.patch - guarded by ['+commited'] skipping pnfs-parovider-fix-19.patch - guarded by ['+commited'] skipping log4j.patch - guarded by ['+mm'] skipping chimera-batch.patch - guarded by ['+commited'] skipping pool-migration-plugin.patch - guarded by ['+mm'] skipping petmission-handler-interface.patch - guarded by ['+acl2'] skipping abstrach-permission-handler.patch - guarded by ['+acl2'] skipping psux-match-fix.patch - guarded by ['+commited'] skipping pool-manager-acl.patch - guarded by ['+pm-acl'] skipping acl-branch-merge.patch - guarded by ['+acl'] skipping level-to-uri.patch - guarded by ['+migration'] applying fix-nfs4-mover.patch Now at: fix-nfs4-mover.patch $ hg qapplied fix-nfs4-mover.patch junit-test-for-chimera-provider.patch pnfs-hadler-cache.patch $
You may list all existing guards:
$ hg qselect -s +19 +acl +acl2 +acl2ik +commited +migration +mm +nfs +obsolete +pm-acl +trunk
At some point, if you decide that guard is not require any more or you may want to change a guard:
$ hg gquard 1-9-0-build.patch -19 +commited
Cherry-Pick
e.g. merge some commits only
- enable transplant extension ( hg.transplant = )
- merge the changes :-)
$ hg transplant -s <some other repository> <rev1>[:<rev2>] ...
Bisec ( or find commit)
There is an easy way to find commit which introduced a problem. It's only a four easy steps:
- write a script to return 0 when test pass and 1 other wise. Here is mine:
grep -q "This should never be in code" && exit 1 exit 0
- mark last know GOOD revision:
$ hg bisec -g <last stable>
- mark first know BAD revision:
$ hg bisec -b <here I found it!>
- let mercurial search for a commit which introduced the bug:
$ hg bisec -c <my-test.sh>
my real code:
$ hg bisec -g 160 $ hg bisec -b tip Testing changeset 174:34ec3850340e (29 changesets remaining, ~4 tests) 15 files updated, 0 files merged, 2 files removed, 0 files unresolved $ hg bisec -c ./bug-test.sh Changeset 174:34ec3850340e: good Changeset 181:e09c9d832b49: bad Changeset 177:82aba55b9609: bad Changeset 175:16d61b5abd95: good Changeset 176:dea80b59c4e0: good The first bad revision is: changeset: 177:82aba55b9609 user: Tigran Mkrtchyan date: Wed Aug 18 12:31:38 2010 +0200 summary: build: fix encoding $
Links
http://video.google.com/videoplay?docid=-7724296011317502612
Last Modified : Sun Dec 8 09:57:14 2019 by Tigran