Last week I've been observing details of integrating source code coming from three different development teams (located in different countries). Each team owns some subset of modules and has R/W access only to those modules. Of course compile dependencies cross the borders in many places, so global changes usually done in one commit had to be split into at least two commits (because of missing W permission for someone).
There was one development branch and one integration branch. Development branch most of this time was in not "buildable" state (permanent build error), so no one was able to ensure changes are not breaking the build before commit until stabilisation. Integration branch was loaded using files copied from development branch when stable state was achieved (I know, lame). This integration style (allowing for non-buildable commits on development branch) blocks parallel integrations (one have to wait for stable state on development branch).
Are there better ways to organise such integration?
Shared Codebase Ownership
In this scenario every team has full write access to all modules and it's possible to create single commit by team T1 that spans module boundaries: refactors module A (owned by T2) AND calling code from module B (owned by T1).
There will be only one "a must" rule: all codebase should be compilable after every commit. Modifications to "not owned" modules should be minimised (only to make code compilable), probably with some "FIXME" left in code.
Doing that operations in single commit allows you (1) to inspect that commit afterwards (2) retain "green build" property after every commit.
Having always-compilable head we will be able to schedule such operations in paralell. Nobody will be blocked (of course teams have to communicate/consult such cross-border changes before commit).
In this case applied changes are visible by diff-ing selected changesets.
Topic Branches
If globally shared codebase is not an idea to be considered we could use short-living branches (called sometimes "topic branches") that get updates from both teams and after stabilisation they are merged back into main branch (and deleted).
Code on topic branch could be unstable, on development branch must be always stable.
Note that merging person should have write access to all "dev" branch (in this aspect this strategy is similar to previous one). I used to place at this point code review process.
In this case pending changes are visible by doing a diff on existing topic branch.
Moving "Stable" Tag
This strategy can be used for file-tracking systems like CVS or Perforce. For those VCS-es one can move tag to new version for subset of files (SVN, GIT, Bazaar will not allow that).
Person that created "stable" commit should create/move some tag to current revision.
$ p4 tag -l STABLE ...
Then anyone interested in stable state would sync to that state:
$ p4 sync ...@STABLE
Then I can fetch fresh (from head) files I'm going to change:
$ p4 sync P1/...
After adding fixes I'm committing the change:
$ p4 submit
and moving stable label for files I've changed (I must check if full build is green before):
$ p4 tag -l STABLE P1/...
In this case pending changes are visible by diff-ing STABLE..head revisions range.
Summary
If some independent activities cannot be performed in paralell it's a bad sign. It means some artificial dependencies were introduced and it results in slower progress for project (caused by serialisation).
In this case missing "W" access was the cause for additional burden. Unstable main branch was a global semaphore that blocked everyone (at least in integration terms).