DVCS comparison for our organisation: decided

John Arbash Meinel john at arbash-meinel.com
Tue Oct 16 16:45:46 BST 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ben Finney wrote:
> Nicholas Allen <allen at ableton.com> writes:
> 
>> Ben Finney wrote:
>>> The developer commits to their own branch without the hook, but
>>> try to commit to the anointed canonical branch and the test suite
>>> runs automatically to determine whether the commit succeeds.
>>>
>> I guess that is another way of doing it. It probably means that if
>> multiple developers commit to the trunk at similar times you will
>> get locking issues (even on Mercurial).
> 
> Not if the pre-commit hook is pre-acquire-repository-lock. That is,
> only acquire the lock if the pre-commit hook succeeds.

Except you then have a different race condition. Which is that 2 people go to
commit at the same time, and the pre-commit *passes* on both sides, but only 1
of them can win. Otherwise the second commit is not based on the first commit
to succeed.

Which in that case probably means "try to commit, pre-commit passes, oops
mainline has updated, pull to update, and try to commit again."

Which can actually happen in an infinite loop if the development is fast
enough, and 'make test' takes long enough.

Again, it depends on your situation. There are a lot of solutions that fit when
the problem space is small.

I've worked with a project that has a 'make test' time on the order of ~2
hours, and especially right before a release, will get 5+ submissions in the
PQM queue. And while it isn't especially fun to wait 4 hours to find out
whether your submission succeeded or not, it would be even less fun to be
waiting 10 hours, and having to do "bzr pull; bzr commit" each time (because
each time someone else beats you to the punch).

Also, you have to watch out for the "easy" way out, which is that hey, 'make
test' passed, don't worry that it is based on another patch. Consider the case:

user1: rename foo() to bar(), and update all references
user2: write a new function baz() which uses foo()

On both sides the test suite will pass, but when combined, they will fail.
user2 hasn't seen the rename yet (so can't use 'bar()') and user1 hasn't seen
the new function baz() to know that it needs to be updated.


Again, if your number of developers is small, or at least the number of commits
to your shared branch is low, you won't run into this often. But be aware, that
using post-commit hooks for this sort of thing, will tend to enforce the
"number of commits to shared branch is low". Because you are creating a large
barrier of entry. So people will be conditioned into doing their own
integrating and committing 1 large change to mainline, rather than several
smaller changes. "Because I don't want to wait 2 hours for each change." With a
PQM in place, the wait is still there, but it is done without the user sitting
and waiting for it.


> 
>> When one person is committing to the trunk and the test suit is
>> being run then he will have to wait until the first developer's
>> commit finishes.
> 
> If the pre-commit hook must be satisfied before even attempting to
> acquire the repository lock, this isn't a problem; the person
> twiddling their thumbs isn't holding anyone else up.
> 
> 
> As for whether this is how Mercurial implements it, I don't know; the
> context of the above was in response to a request for feedback on what
> I think Bazaar should do.
> 

To enable an arbitrary command to be run from a post-commit hook is a plugin
that looks something like:

import os

from bzrlib import (
  branch,
  )


def pre_commit_command_hook(local, master, old_revno, old_revid, future_revno,
			    future_revid, tree_delta, future_tree):
  if master is not None:
    config = master.get_config()
  else:
    config = local.get_config()
  command = config.get_user_option('pre_commit_command')
  retcode = os.system(command + ' ' + local.base)
  if retcode != 0:
    raise Exception('Pre-commit failed')

branch.hooks.install_hook('pre_commit', pre_commit_command_hook)



At this point, the pre-commit command is defined in the ~/.bazaar/*.conf files
(or in .bzr/branch/branch.conf).

Just to point out, there are still some problems with this (though I bet the hg
one has them as well).

a) Partial commits "bzr commit -m 'hello' x y" only commits the changes to x
and y, not the changes to z. Which means your "make test" may be running with
the wrong information.

b) Do you care whether the branch is bound or not (though hg doesn't have that
as an option). A branch with a 'master' branch will require the commit to
succeed on the master rather than only locally. *Very* useful for keeping a
copy of 'trunk' that you just 'update &merge & commit' rather than dealing with
the tricks of 'merge & commit & push [fail] & revert & pull & merge & commit...
etc'


Anyway, certainly Mercurial's pre-commit hooks are easier to set up than a PQM.
But they are also more simplistic as to what they can solve.

If you are trying to handle "no trailing whitespace in files" they probably
handle that just fine.

If you are like bzr.dev and have a test suite with 8k tests that takes about
5-10 minutes to run, you might be okay. It is a bit long for a user, but isn't
terrible. And you are only going to get collisions some of the time.

If you are a larger project with a 2-hour test suite, you probably will find it
wholy unsatisfactory.

Then again, you can also run the project like gcc. Which uses more of a style
like SVN's Cruise Control. Which has everyone committing on 'trunk', which is
allowed to break from time to time. Cruise Control runs the long-running
test-suite when it can, and just informs the users when they need to go back
and fix things (potentially long after the fact.)


We in the Bazaar group really like the fact that our mainline *always* passes
*all* tests (at least on the platform it is tested on). Because it gives us a
very strong feeling that you can always dogfood on tip (and most of the main
developers do). It is guaranteed to be quite stable. And it means that when
release time rolls around, we generally just branch off of tip, set the release
numbers, and call it a release.

Anyway, I've probably written too much as it is. Just be wary of the simple 80%
solutions, that won't fit when you get into the last 20%.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHFNyqJdeBCYSNAAMRAs7TAJ44PzzRlFOHaPWlsXW9d4BlsomAqwCfep5S
r7wdj0Fw/XtPZjHvBDpJ9jI=
=VbCD
-----END PGP SIGNATURE-----



More information about the bazaar mailing list