Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's suppose (for simplicity) that we have an application featuring client and server; is there a better idea to use one repository for both or a pair of separate repositories?

Mixing them will probably make easier to track correlated changes and maintain correlated branches (i.e. protocol evolution), but on the other hand will make the individual development more cluttered...

share|improve this question
    
And what's wrong with using separate branches? A developer only needs to have the branch he's currently working on open locally, so he won't even see the stuff that's only in the other branches anyway. But, if he needs to get into the branch for some reason, he can. –  Spencer Rathbun Dec 20 '11 at 19:05
    
@SpencerRathbun - Using separate branches like this is a recipe for disaster. It would be really difficult to share files between server and client, especially interfaces and system documentation etc. With a DVCS it would require you to clone all of the client and server commits, even if you only wanted one, and wouldn't give you any hint as to which client and server versions would work together. Compared to a monolithic (single) repository or a modular (multiple) repository breakdown, you actually get the worst of both worlds. –  Mark Booth Dec 20 '11 at 20:02
    
@MarkBooth Humm, I was thinking of project sections in each branch, since he's indicated that they will be sharing code. Just tag each section as the appropriate branches, and you're good. Does your DVCS not allow a file/commit to have multiple tags? –  Spencer Rathbun Dec 20 '11 at 20:22
add comment

5 Answers

up vote 8 down vote accepted

In you are using git or mercurial, then you might want to look at submodules or subrepositories.

The client and server would be in their own repository, but would be tied together at the super-repository level. This would allow you to do one checkout at the top level and git or hg would check out the appropriate commit of each of the submodules/subrepositories.

By only committing to the super-repository when both client and server were appropriate to each other, the super-repository would only ever give you the option to check out a working system - so you would never try to run the new client against an old server.

Submodules give you many of the advantages of using separate repositories, along with many of the advantages of a single monolithic repository.

This answer is not intended to advocate git or hg over other SCMs, it just happens to be that I only know these SCMs well enough to know that this option exists. I haven't found an equivalent thing in svn for instance.

share|improve this answer
    
Now THAT'S an interesting feature. I'd be interested to see some proper case studies of its use, I'd not even heard of it before! –  Ed Woodcock Dec 20 '11 at 17:14
    
A similar thing in subversion is external definitions: svnbook.red-bean.com/en/1.0/ch07s03.html. However it works in a slightly different way. –  liori Dec 20 '11 at 19:54
    
@liori - From reading that svnbook chapter, it doesn't look like svn externals are quite the same thing as git submodules or hg subrepositories. Can you specify what version the external is, so that if you check out main:r12345 you get external1:r11234 and external2:r10987 but if you check out main:r15432 you get external1:r11345 and external2:r14321? –  Mark Booth Jan 4 '12 at 14:34
1  
@MarkBooth: yes, you can. On that page you can see parameters that look like -r12345 -- those define which revision do you want to get. And since svn:externals property is versioned like any text file, you can have different values for -r for each revision. Also, you are browsing ancient 1.0 documentation. External definitions were changed in 1.5, and current version is 1.7. See: svnbook.red-bean.com/en/1.7/svn.advanced.externals.html –  liori Jan 4 '12 at 19:21
    
@liori - Ah thanks, the more recent version of the page is much clearer than the original one you linked to. –  Mark Booth Jan 5 '12 at 0:55
add comment

Separate!

In fact, I'd probably have three repositories, one for the Client and corresponding client-only libraries, one for the Server (and corresponding libraries), and one for the shared libraries (incorporating the API interfaces that expose the functionality between the two, plus any other shared code). I think that's really the key, the shared code should go into a separate repository of its own. That way you can make sure that the interoperability between your client and server is both always at the same version AND is isolated from the design of each of its consumers.

Obviously, this is not always possible, depending on the particular communication framework you're using, but there's likely to be shared code that dictates the format of the data-transfer objects or the handshake steps in your custom protocol (or some other example).

Assuming you have a fairly decent Continuous Integration and QA setup (a fairly large assumption, in my experience, but one I'm going to make nonetheless. If you don't have a QA department you should at least get some CI) you shouldn't need to use the single-repo pattern as a defense against possible code mis-matches, either your CI server will flag up library-interoperability or your QA team will catch runtime errors (or, even better, your Unit Tests will).

The benefits of split repositories lie in the ability to separately version separate parts of a system. Want to take a copy of last week's Server and run it with this week's Client, to try and lock down the root of a performance issue? No worries.

share|improve this answer
add comment

In Mercurial, this scheme can be used, using -> to denote subrepo relationship:

product -> client -|-> (many components)
                   |->  shared component A

        -> server -|-> (many components)
                   |->  shared component A

Product has subrepos client, server. Each of those has their components as subrepos, possibly at least one subrepo shared between the two.

Tagging should probably be done on the first two levels, not below that.

Commits are done on the component level, the superrepos effectively track named branches and versions of the product. Named branches/bookmarks are usually better than clone branches for usability (ie trainability) and compatibility with subrepos.

hg tends towards the assumption that superrepos are the product, and commits are done at the top level, but that doesn't work particularly well when multiple products use the same components. :-)

I don't think that this scheme will change much if transitioned to git, but I haven't tried it out in git yet.

share|improve this answer
add comment

Forget about the repository for a moment. How would you organize the two projects on your machine if you weren't sharing with anyone? How would the rest of the team do it? Would you...

  • Put all the source files for both client and server in the same directory?

  • Create a main project directory that contains subdirectories for the client and the server?

  • Keep the two projects completely separate?

Once you come to some consensus about that as a team, you're ready to check the projects into your code repository. All the revision control tools that I can think of are happy to reproduce any directory structure you like -- they don't care one bit about which file belongs to which project. And the difference between having one repository or two (or six) is usually not that great, aside from minor administrative differences.

For example, with Subversion, the biggest difference between separate repositories for client and server and a single combined repository is in the way the revision numbers change. With a singe repository, the version number will increase each time you commit code to either client or server. With separate repositories, a commit to the server project won't change the head revision number for the client.

share|improve this answer
add comment

This is a configuration management problem, not a revision control problem. As always, a programmer using a screwdriver to hammer in a nail. Work out how you will manage you configurations, the the revision control will take care of itself.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.