Git structure for java project

code-organizationdesigneclipsegit

I know there are multiple posts on similar problems, so please be kind with me.
I am asking for suggestions I have not thought of and for good advice.

I have a java "project" that is structured in a server-client pattern.
There are some classes that are common to both parts but most of it is either server (backend and control logic) or client (GUI). To not write one monolithic application (where the client depends on JDBC jars) I decided to split the project into multiple eclipse projects:

  • proj_server (where JDBC is needed)
  • proj_client
  • proj_common
  • proj_test

In proj_test there is some code to test parts of the client/server. I setup eclipse such that both server and client depend on the common module.

Now I use git to manage all these eclipse projects.
My first thought was to manage all parts in separate repos as suggested by git.
But I have the problem that I loose the relation of the different commits: Any modification in the proj_common will typically reflect some data type modification. This makes the new version incompatible with old commit in the other projects.

I then thought of several possibilities:

  1. Using of git submodules
  2. Using of git subtree
  3. Using of a single git repository that contains the modules together
  4. Using different repositories and adding regularly tags to the commits to keep track of the relations

The solution 1 has the problem that it is quite heavy to maintain. Especially if you want to check in multiple small modifications you have to go multiple times "around the folders" to add/commit and then pack it all in the main repository up.

The subtree method might work well as far as I have read with a bunch of scripts to manage the git calls. The main disadvantage is that subtree fits perfectly if most work is done in the main repository and updates to the imported repos happen occasionally. If the updates happen merely in the subprojects the history of the main projects gets quite crumpled.
On branching it might get complicated.

The solution number 3 is my favourite solution so far as everything is kept tight and branching is done without any problem.

The solution 4 is mainly what is done now, but no tag have been created yet (pre-alpha, thus no sense in creating tags). As the project grows this might get also very nasty and error-prone.

What would you suggest? One of the given solutions or did I miss the one perfect solution?

Edit:

I have found the following related posts: a, b, c and d.
Unfortunately the big picture is not clear.
In a (second answer!) and d the advice tends towards multiple repositories in different files.
But they do not explicitly state how to manage the relationship of the different commits.
That is you cannot go for the running configuration at Jan 10th 2013 for example without looking at the history explicitly for all subprojects.
In b solution 3 is suggested.
In c a comparision is made. They first had something like multiple manually managed projects but then migrated to solution 3.

In all these Q&As the first two solutions were at most mentioned but not suggested by the answering persons.
In the net you can find much about git submodule that tells you that you get quite much overhead by it (e.g. here or here).

The problem is (as far as I can see) that in practice I will have not only one project with some reference to one or more libraries.
In this case (hopefully) the library would not change regularly and the coding takes place in the "main" repository.
In this case all the advances solutions (subtree, submodules, …) might be very useful.

In my case on the contrary I have only a dummy master repository that holds the four subprojects in sync.
These subprojects themselves are under high development.
So it is a critical part that the contribution to the different online (sub)projects is straight forward.
Not much additional magic with git.

In another site they suggest solution 1 but I am unsure what their main development goal is: The main repository or the imported library.

I want to avoid getting into trouble and later have to migrate to another system. Thus I ask for advice of somebody who might have done similar things.

Best Answer

For this kind of work, I suggest you to learn about Maven which deals with dependency compatibility (among a lot of other things).

With Maven, you could for example use one of these two ways:

Either the "standard" way: by creating a Nexus repository which you will feed with a compiled jar of each version of your common package and to fully exploit maven/nexus the version(s) of JDBC you use. Each time you build your project from any commit, the versioned config file will be read and will use the good revision of your library "common".

(I say Nexus, but there are others software doing the same thing, I've also heard of one named Artifactory).

Or, you could make a more complicated script which, when you build your server or client project, go download the source of your library on your "common" repository and build it.

Maven may seems a bit overkill and is (in my opinion) a pain to learn alone, but it's handy, powerful, and is the professional standard in Java and works seamlessly with Eclipse.

As for the Maven usage, the Nexus way is (depending on your scripting skill) a bit heavier to init, but more standard, easy to scale with your project, and can be used for all your other future projects.

If you're working in a professional context, I strongly advise to look for a colleague knowing it to help you mavenize your project.

Related Topic