7

Scenario: Various products made up combinations of the smaller projects. A few different versions of each product in dev, release and maintennace (bugs/patches/minor releases).

Most the the team use various third party tools and libraries for dev and for release (common two are XUnit for dev, and AutoMapper in product). They're fans of version controlling these tools/libraries where it makes sense.

I cannot seem understand the best way to organise the structure in mercurial. In the the central SVN style, I'd organise by having the the third party tools as their own projects and then having small builds for the projects that would grab the output of the other projects, and then a release project that would be built from the built projects. All would be in a hierarchy,

(dev branch)

Root/dev/ProjectX/
Root/dev/ProjectY/
Root/dev/ThirdParty/XXX -- could be a 3rd party lib
Root/dev/ThirdParty/YYY -- could be a 3rd party lib

(branch 1)

Root/release1/ProjectX/
Root/release1/ProjectY/
Root/release1/ThirdParty/XXX 
Root/release1/ThirdParty/YYY

(branch 2)

Root/release2/ProjectX/
Root/release3/ProjectY/
Root/release2/ThirdParty/XXX 
Root/release2/ThirdParty/YYY

etc.

Here comes the rub, due to the way that developers keep their machines upto date (using NUGET package manager) the third party items all have to be in the ThirdParty folder to to ensure that the devs don't have to have multiple copies of these libraries for each project.

My question is this:

If they implement mercurial should implement a simmilar strategy (big repo) and clone/branch here or should they break up the repository say at the project level and clone/branch these. In the latter case would they have a product/version branch/repo? I know they'd prefer a distributed model if it works better in the long term, even if the pain of learning a new workflow is hard initially.

I've read http://nvie.com/posts/a-successful-git-branching-model/ and a number of articles but I'm still unsure as to how to organise.

Preet Sangha
  • 64,563
  • 18
  • 145
  • 216

1 Answers1

6

Basically, you make a separate repo for each product, each project, and each third-party library, and then you combine them as appropriate in subrepositories. On your central server (or servers), I would probably set up a structure of bare repos like this:

  products/ProductA/
           ProductB/
           ProductC/   
  projects/ProjectA/
           ProjectB/
           ProjectC/   
thirdparty/ThirdPartyA/
           ThirdPartyB/
           ThirdPartyC/

This way you have exactly one copy of each repo on your central server. You don't need to make separate repos for each branch, because mercurial can hold multiple branches in one repository.

Then, when someone checks out a Product in their local repository, you use the subrepo mechanism to also check out the working trees for the appropriate projects and third party libraries. On your local disk, the structure will look like this:

ProductA/
         ProjectA/
         ProjectB/
         ThirdParty/
                    ThirdPartyC/

This looks different than on the central server because there you don't have working trees, only pointers into the subrepos.

Karl Bielefeldt
  • 47,314
  • 10
  • 60
  • 94
  • Thanks, how do you suggest product be organised – Preet Sangha Aug 15 '11 at 09:37
  • Excellent. If I may, just to clarify. Say I fix in the Projects/ProjectA. I now want to push to productB, will the subrepos allow the merge of the changeset ok? Is there a special syntax? – Preet Sangha Aug 15 '11 at 23:32
  • 1
    There are a number of special syntax things you need to keep in mind. Too many to cover here, so you really need to read [the docs](http://mercurial.selenic.com/wiki/Subrepository?action=show&redirect=subrepos). In a nutshell, you have to pay extra attention on the pulls, because one product may not be ready to update to the latest revision of a project yet, so hg doesn't automatically do it until requested. – Karl Bielefeldt Aug 16 '11 at 03:04
  • 1
    @Preet - Basically the `ProductA` manages how it uses the sub repo `ProjectA`, so if `ProductB` updates `ProjectA` with a bug fix, `ProductA` only gets it when you specifically update `ProductA`s `ProjectA` - this allows you to manage the regression testing on a per product basis. Also note that there is no need to merge, just update the sub-repo and commit the new state of the Product. – Mark Booth Aug 16 '11 at 10:32
  • This looks just like what I'm after. @mark in addition to Karl's links can you suggest any further reading please? – Preet Sangha Aug 17 '11 at 08:48
  • Karl, feel free to edit these comments into your answer. That way we can tidy up the comments later. – Mark Booth Aug 17 '11 at 09:30
  • @Preet - The obvious one is Bryan O'Sullivan's [Mercurial: The Definitive Guide](http://hgbook.red-bean.com/) but that still doesn't appear to have a subrepos section. I would also recommend the [Mercurial Mailing Lists](http://mercurial.selenic.com/wiki/MailingLists), particularly the [general mailing list](http://www.selenic.com/mailman/listinfo/mercurial/) and the [subrepos tag](http://stackoverflow.com/questions/tagged/subrepos) here on StackOverflow. – Mark Booth Aug 17 '11 at 09:35