We often have common code that we’d like to share across different projects. (For example, our Utility library is useful in both the desktop software and in an ASP.NET website.)
One way of sharing code is to place it in its own repository, and add it as
a submodule to all repos
that need it. But submodules are a bit of a pain to work with on a daily
basis (for example, git checkout
doesn’t automatically update submodules
when switching branches; you have to remember to do this every time, or
create an alias).
Submodules also make it difficult to “compose” libraries. For example, App1
and App2 might both use Utility, but they might also both use Framework,
a desktop application framework that’s not general-purpose enough to live in
Utility, but is in its own repo. If Framework itself uses Utility as a
submodule, then the App1 and App2 repos might contain both /ext/Utility
and /ext/Framework/ext/Utility
. This is a maintenance nightmare.
Our choice at Logos is to clone all necessary repositories as siblings of
each other. In the App1 example above, we might have C:\Code\App1
,
C:\Code\Framework
and C:\Code\Utility
as independent repos. Dependencies
are expressed as relative paths that reference files outside the current
repo, e.g., ..\..\..\Utility\src\Utility.csproj
. We’ve written a shell script
that clones all necessary repos (for a new developer) or updates all
subfolders of C:\Code
(to get the latest code).
By convention, developers are working on the master
branch on each repo
(or possibly a feature
branch in one or more repos for a complex feature).
It’s theoretically possible for someone to push a breaking change to
Utility and forget to push the corresponding change to App1 (a problem
that submodules do prevent), but this happens very infrequently.
Posted by Bradley Grainger on November 17, 2012