I’m involved into several projects, luckily all of them are using Git as VCS for code storage.
When working in a team, it’s very important to pre-define certain rules that everyone will follow to make everything straightforward and expected. This will allow to simplify general workflow and to decrease cognitive load when switching between tasks/branches/projects.
Before going into branch management in some of my projects, I would like to first cover the repository usage for your projects.
Project as a monorepo with single build tool and common dependencies
For those unfamiliar – that’s when you have several libraries/plugins/addons, that are part of a single product, in the same repository.
Example: you are developing various plugins for WooCommerce. That means your repository has a structure like this (and locally you pull it into
.github/ .gulp/ node_modules/ plugin1-for-woocommerce/ plugin2-for-woocommerce/ vendor/ woocommerce/ query-monitor/ .gitignore composer.json gulpfile.js package.json
As you can see, all plugins share the same build tool (
.gulp directory and associated main
.lock files should be in the repository as well, I’m just no including them for sanity.
This approach is the most disc space efficient, but requires a very careful and accurate build tool rules and dependencies version management. You will also need to have a unified way to build things (translations, zip files, SCSS->CSS, etc) across all of your plugins inside the repository, and make sure that every one uses certain correct non-conflicting version of dependencies.
If you use Composer autoloading – you will have a terrible headache when you make a distribution zip archive – you don’t want to include in
plugin1 dependencies from
plugin2. Of course, this is possible, but you might end with writing lots of custom scripts for
Project as a monorepo with multiple build tools and independent dependencies
That’s basically the same as above, with a small but very important difference in directory structure and the way build tools (
gulp in my example) are used.
.github/ plugin1-for-woocommerce/ ├── .gulp/ ├── node_modules/ ├── vendor/ ├── composer.json ├── gulpfile.js └── package.json plugin2-for-woocommerce/ ├── .gulp/ ├── node_modules/ ├── vendor/ ├── composer.json ├── gulpfile.js └── package.json woocommerce/ query-monitor/ .gitignore
Each plugin has its own copy of build tools,
- simplifies building and managing dependencies for each plugin – as they are independent;
- is very good, when you have a core plugin,
,and all others :
plugin3etc – depend on it (aka addons). So quite often you need to make a big change in a core plugin, and all “addons” will require a minor change in behavior (like filter usage).
For both of these monorepo approaches:
- you make only 1 commit when you modify something similar (or the same) for both plugins: adding a footer link in the admin area of a plugin, for example;
- you can automate
foreach of the plugins by using a Git hook
post-checkout– so developer initially runs a single
andeverything is set up after its done.
Product with several repositories (projects)
You take each custom
pluginN-for-woocommerce directory from above and put it into own repository. That will mean that when you make changes in admin area of your plugins (like the new footer link) – you end up with multiple commits to each repository.
This approach is also more complex at the beginning, because every developer (or when you change your working machine: home/office, Mac/Windows etc) will need to:
- request access to each of the separate repositories;
pullthem one by one into specific places;
foreach of them.
So several repositories provide more granular access control (which needs to be managed), complicates initial development, requires lots of similar commits across your various repositories, might duplicate common build steps.
What to select?
There is no an easy answer. You select the road to take depending on your vision and your project.
I think that highly coupled projects might benefit from being in a single repository (aka monorepo), but with own dependencies. You can always make a mix of those 2 monorepo examples:
- the single build tool (like a top-level
.gulpdirectory and a single
gulpfile.js) and a special top level
package.jsonjust for building (of course if you are
,because you can have a Robo too);
- each plugin has its own
package.json(which just won’t have
gulpand everything related to actually building it).
But if all of your plugins are totally separate and do not relate to each other – let them be in separate repositories. In case something is in common, like an admin area handling (basic skeleton) – you can make it a library, release via the P
Featured image by Sear Greyson.