We have a gradle project `A` with composite build ...
# community-support
t
We have a gradle project
A
with composite build child projects
X
and
Y
.
A
,
X
and
Y
are all version controlled with git and has their own git repositories.
X
and
Y
are git submodules for
A
. This set up makes development very easy and the structure is quite clean. Trouble is, now we have to add a shared library
S
which both
X
and
Y
depends on. Is there an elegant way to do this while still using git submodules and gradle composite builds?
I have a few general ideas: 1. Use symbolic/soft link such that
X
and
Y
share the same copy of
S
. 2. Use git worktree to achieve the same as (1). 3. Make
S
a regular (non-composite) build, then
X
and
Y
simply includes its artifact.
I'm sure many have stumbled across this problem before, mind sharing your thoughts? I would really appretiate any comments 🙂
v
I'm sure not many stumbled across that problem, as Git submodules are not very widespread used and are imho not to helpful for the "developing things in parallel" use-case.. :-D Try just having S as submodules of A, X, and Y, and include it in A before including X and Y. That might achieve an acceptable result, but I'm not sure.
1
t
What kind of structure would you recommend without git submodules?
Have all the projects open Build artifacts on
X
Y
S
, "publish" them to maven local repository. Then temporarily set `A`'s dependency to maven local repository during development?
v
Using composite builds is fine as long as the Gradle versions in the projects are compatible (optimally identical) as the Gradle version of the main build is used for all included builds. I just don't think Git submodules are too suitable for parallel development, as you pin a submodule to a specific commit and if you pin it to one but then not push the submodule but the parent it is not found at other computers, or if you push the parent and then try to push the submodule but first have to rebase onto incoming changes the commit ID changes and thus the parent also again does not find the commit in the submodule at other computers and so on. Git submodules imho are fine if you want to depend on a specific commit of an externally maintained project but do not often too own changes in it. Maven Local I would avoid wherever possible, as it is broken by design, or at most with having it as last option in the list of repositories and only with a repository content filter specifying exactly which artifacts are known to be good in it and should be used from it. If source dependencies in Gradle would be developed further one day, that would probably be the imho proper way to go, for now I would maybe use melix's includegit plugin. Or you could also have some logic like "if repository is found at
../the-submodule
then include that build, otherwise not", because the dependency declaration is the same either way, so when normally building the project you use published versions and for local development you could use composite build or something like that.
👍 1
t
...as you pin a submodule to a specific commit and if you pin it to one but then not push the submodule but the parent it is not found at other computers, or if you push the parent and then try to push the submodule but first have to rebase onto incoming changes the commit ID changes and thus the parent also again does not find the commit in the submodule at other computers and so on.
This limitation is usually worked around by 1. always pushing the library project first before the parent project, and 2. push commits on the library project as frequently as possible. And yes it does have some issues if rebase is used, but in those cases we could amend the commit on the parent project, so that it points to the new rebased commit of the library project. The issue in this is that if many commits in the parent project have changed, it would be a pain to change all of them. 🤔
Thanks for suggesting the includegit plugin! it looks excellent, I will definitely try it out
It seems like using
includegit
cannot solve the issue with duplicated copies of
S
, for example when both
X
and
Y
use
includegit
to checkout
S
, where it would result in a copy of
S
under
X
and another copy under
Y
. Which is reasonable because
X
and
Y
could point at different revisions of
S
. The use local copies method might solve this
local.git.jdoctor
, but then we lose information on which version of
S
is being used on
X
and
Y
v
I think you can in that plugin tell which worktree to use if there is one already. But did you try my suggestion of also including S in A before including X and Y. Iirc that might then "override" the included on in X and Y eventually.
👀 1