We are doing projects, but we reuse a lot of code between the projects and have lots of libraries that contain our common code. As we implement new projects we find more ways to factor out common code and put it into libraries. The libraries depend on each other, and the projects depend on the libraries. Each project, and all libraries used in that project, need to use the same version of all the libraries they are referring to. If we release a piece of software we will have to fix bugs and maybe add new features for many years, sometimes for decades. We have about a dozen libraries, changes often cut across more than two, and several teams work on several projects in parallel, making concurrent changes to all these libraries.
We have recently switched to git and set up repositories for each library and each project. We use stash as a common repository, do new stuff on feature branches, then make pull requests and merge them only after review.
Many of the issues we have to deal with in projects requires us to do changes across several libraries and the project's specific code. These often include changes of library interfaces, some of which are incompatible. (If you think this sounds fishy: We interface with hardware, and hide specific hardware behind generic interfaces. Almost each time we integrate some other vendor's hardware we run into cases our current interfaces did not anticipate, and so have to refine them.) For example, imagine a project
P1 using the libraries
L1 also uses
L3 as well. The dependency graph looks like this:
<-------L1<--+ P1 <----+ ^ | <-+ | | | | +--L2 | | ^ | | | | +-----L3---+
Now imagine a feature for this project requires changes in
L3 which change the interface of
L3. Now add projects
P3 into the mix, which also refer to these libraries. We cannot afford to switch them all to the new interface, run all the tests, and deploy the new software. So what's the alternative?
- implement the new interface in
- make a pull request for
L3and wait for the review
- merge the change
- create a new release of
- start working on the feature in
P1by making it refer to
L3's new release, then implement the feature on
P1's feature branch
- make a pull request, have this reviewed, and merged
(I just noticed that I forgot to switch
L2 to the new release. And I don't even know where to stick this in, because it would need to be done in parallel with
This is a tedious, error-prone, and very long process to implement this feature, it requires to independent reviews (which makes it much harder to review), does not scale at all, and is likely to put us out of business because we get so bogged down in process we never get anything done.
But how do we employ branching and tagging in order to create a process that allows us to implement new features in new projects without too much overhead?