15

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...

3
  • 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. Dec 20, 2011 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, 2011 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? Dec 20, 2011 at 20:22

6 Answers 6

12

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

The client, server and their interface files would be in their own repositories, 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 or vice-versa.

Submodules/subrepositories give you all of the advantages of using separate repositories, along with the advantages of a single monolithic repository, at the expense of a little extra complexity.

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 don't understand how svn externals work for instance.

3
  • 1
    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 James
    Dec 20, 2011 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, 2011 at 19:54
  • 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, 2012 at 19:21
6

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.

1

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.

1

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.

1

The simplest approach is to use a single repository, so unless you like complexity for complexity's sake, then that should be the default choice in the absence of compelling arguments otherwise.

Is the client and server development going to be carried out by different organisations? Will there be multiple implementations of the client (or server)? Is the client open source and the server implementation secret? If the answer to all these questions is "No", then anything more complex than a single repository is likely to bring only inconvenience for no benefit.

If you do choose to maintain separate codebases, you will need clear policies about how this is administered, in order to avoid incompatibilities and dependency hell. After working through the first few hiccups, you might end up discovering that the safest thing is to always check out both repositories together, build them together, and deploy them together...which obviously defeats the whole purpose of separating them!

Modularity is a nice property to have, but splitting repositories is not a tool to achieve that. As the previous paragraph implies, you can have highly coupled components that are split over multiple codebases (undesirable), and likewise you can have highly modular components within the same codebase (desirable).

On more than one occasion, I have advocated (successfully) for my team to merge existing git repositories, because it simplified development and deployment.

0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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