<p class="wp-block-paragraph">That’s the problem.</p>
<p class="wp-block-paragraph">What is behind a repository platforms like github, gitlab, gitea, etc.? Features:</p>
<ul class="wp-block-list">
<li>webhooks</li>
<li>actions</li>
</ul>
<p class="wp-block-paragraph">Both are based on concept of “trigger”: to trigger a webhook, to trigger an action.</p>
<p class="wp-block-paragraph">The point of multi-repo is to trigger only specific action: for example, I do not want to rebuild docker image for a service if I just updated the GUI that is deployed by another action.</p>
<p class="wp-block-paragraph">So the main point to face is action/trigger conflict in a mono-repo.</p>
<p class="wp-block-paragraph">There is also tags: a git repo support tag and releases based on tagging, if the repository is unique, there must be an unique release, but if the project is made of multiple subproject, who own the tag? What is it referred to the tag v0.1.198? Is it the tag for docker image? For the ReactJS GUI? For the deployment yaml? For what?</p>
<h2 class="wp-block-heading">A multi-mono-repo approach</h2>
<p class="wp-block-paragraph">The natural solution comes from git subtree or submodule. The former was the first one, the latter came …later. The choice for multi-mono-repo is to use git subtree.</p>
<p class="wp-block-paragraph">This article <a href="https://www.geeksforgeeks.org/git/git-subtree-vs-git-submodule/">https://www.geeksforgeeks.org/git/git-subtree-vs-git-submodule/</a> gives good points for subtree: it fit better in an environment where the main repository is supposed to update the repository subtree.</p>
<h3 class="wp-block-heading">How to work with subtree</h3>
<p class="wp-block-paragraph">I just paste from the article cited above:</p>
<ul class="wp-block-list">
<li>Add the remote repository as a remote in your local repository:</li>
</ul>
<pre class="wp-block-preformatted">git remote add -f <remote-name> <repository-url></pre>
<ul class="wp-block-list">
<li>Pull the remote repository into your project as a subtree:</li>
</ul>
<pre class="wp-block-preformatted">git subtree add --prefix=<prefix> <remote-name> <branch> --squash</pre>
<ul class="wp-block-list">
<li>Make changes to the subtree as needed and commit them.</li>
<li>Push changes to the subtree’s repository:</li>
</ul>
<pre class="wp-block-preformatted">git subtree push --prefix=<prefix> <remote-name> <branch></pre>
<ul class="wp-block-list">
<li>Pull changes from the subtree’s repository:</li>
</ul>
<pre class="wp-block-preformatted">git subtree pull --prefix=<prefix> <remote-name> <branch> --squash</pre>
<p class="wp-block-paragraph">Arrange the mono-multi-repo this way:</p>
<pre class="wp-block-code"><code>.
├── .agents
│ └── skills
├── deployment-service-a
├── jenkinsfiles
│ ├── build-gui
│ │ └── Jenkinsfile
│ ├── test-service-a
│ │ └── Jenkinsfile
│ └── test-service-a-b
│ └── Jenkinsfile
├── my-gui
│ └── package.json
├── README.md
├── service-a-b-docker
│ └── go.mod
└── service-a-docker
└── Makefile
</code></pre>
<p class="wp-block-paragraph">I would keep just README.md, .agents, and deployment-service-a in the main repo. Everything else go into subtree. So:</p>
<ul class="wp-block-list">
<li>tagging is effective and specific to each branch</li>
<li>.agents and SKILL are becoming the way to define a coding standard, so the main repo contains the coding standard for the whole project, and every one can contribute to coding standard, related to their own branch of expertise, everyone can propose PR on coding standard, etc.</li>
<li>triggers are effective, since every subtree</li>
<li>jenkinsfile (or whatever-ci-and-cd-tool-used) may be unique or multiple, depending from triggering requirements of the tool</li>
<li>deployment-service-a is something that should fit the ArgoCD requirement, it can stay on main repo or it could have its own repo.</li>
</ul>
<h2 class="wp-block-heading">Subtree and freedom of choice</h2>
<p class="wp-block-paragraph">Integrating this with multiple deployment environments can be challenging and arguable. But subtree is the most versatile option: it supports integration of specific branches.</p>
<p class="wp-block-paragraph">Ok, but what if I need to keep multiple branch of main-repo referring to different branch of referred sub projects? Well, in fact this feature is only supported by submodule: metadata for the included submodule contains branch name or tag information.</p>
That’s the problem.
What is behind a repository platforms like github, gitlab, gitea, etc.? Features:
Both are based on concept of “trigger”: to trigger a webhook, to trigger an action.
The point of multi-repo is to trigger only specific action: for example, I do not want to rebuild docker image for a service if I just updated the GUI that is deployed by another action.
So the main point to face is action/trigger conflict in a mono-repo.
There is also tags: a git repo support tag and releases based on tagging, if the repository is unique, there must be an unique release, but if the project is made of multiple subproject, who own the tag? What is it referred to the tag v0.1.198? Is it the tag for docker image? For the ReactJS GUI? For the deployment yaml? For what?
A multi-mono-repo approach
The natural solution comes from git subtree or submodule. The former was the first one, the latter came …later. The choice for multi-mono-repo is to use git subtree.
This article https://www.geeksforgeeks.org/git/git-subtree-vs-git-submodule/ gives good points for subtree: it fit better in an environment where the main repository is supposed to update the repository subtree.
How to work with subtree
I just paste from the article cited above:
- Add the remote repository as a remote in your local repository:
git remote add -f <remote-name> <repository-url>
- Pull the remote repository into your project as a subtree:
git subtree add --prefix=<prefix> <remote-name> <branch> --squash
- Make changes to the subtree as needed and commit them.
- Push changes to the subtree’s repository:
git subtree push --prefix=<prefix> <remote-name> <branch>
- Pull changes from the subtree’s repository:
git subtree pull --prefix=<prefix> <remote-name> <branch> --squash
Arrange the mono-multi-repo this way:
.
├── .agents
│ └── skills
├── deployment-service-a
├── jenkinsfiles
│ ├── build-gui
│ │ └── Jenkinsfile
│ ├── test-service-a
│ │ └── Jenkinsfile
│ └── test-service-a-b
│ └── Jenkinsfile
├── my-gui
│ └── package.json
├── README.md
├── service-a-b-docker
│ └── go.mod
└── service-a-docker
└── Makefile
I would keep just README.md, .agents, and deployment-service-a in the main repo. Everything else go into subtree. So:
- tagging is effective and specific to each branch
- .agents and SKILL are becoming the way to define a coding standard, so the main repo contains the coding standard for the whole project, and every one can contribute to coding standard, related to their own branch of expertise, everyone can propose PR on coding standard, etc.
- triggers are effective, since every subtree
- jenkinsfile (or whatever-ci-and-cd-tool-used) may be unique or multiple, depending from triggering requirements of the tool
- deployment-service-a is something that should fit the ArgoCD requirement, it can stay on main repo or it could have its own repo.
Subtree and freedom of choice
Integrating this with multiple deployment environments can be challenging and arguable. But subtree is the most versatile option: it supports integration of specific branches.
Ok, but what if I need to keep multiple branch of main-repo referring to different branch of referred sub projects? Well, in fact this feature is only supported by submodule: metadata for the included submodule contains branch name or tag information.