We have not used submodules; What we have done is branching strategy
Every micro-service has its own folder under base_folder folder.
There is a release branch --> currently one master ( this has everything)
There is an interface branch --> interfaces ( this has only interfaces like for example protobuffer/ grpc files for all services) . This branch is always merged to master
Each service has a branch --> sprint_service_name where code is pushed (for code review ) and a merge request created to master branch
Code flow
For new component
git checkout interfaces
git checkout -b sprint_service_name
(create branch from interface branch)
For existing component
git checkout sprint_service_name
git fetch origin interfaces
git merge origin/interfaces (don't use git merge origin interfaces !!)
(or for above two steps git pull origin interfaces)
Here is a Developer flow
Push to sprint_service_name branch and create merge request to master branch
git push origin sprint_service_name
Branch flow
sprint_service_namexxx --> Merge Request --> master
sprint_interfaces --> Merge Request --> Interfaces -->master
interfaces --> sprint_service_namexxx (by all, every day)
All common parts will be in interfaces branch
(you can have any number of private branches; But be careful not to merge of master into sprint_service_name or master into interfaces ; else unwanted files will be in your branch)
Pros
Each micro service will have only its code and interfaces folder
Cons
I have seen that the below flow does not always happen ideally, like
sprint_interfaces --> Merge Request --> Interfaces -->master
It is more like
sprint_interfaces --> Merge Request --> master
Which means that someone has to manually take Interfaces folder from master and merge to Interfaces branch. But this is just a discipline thing and has not broken anything