A tool for managing multi-project systems and libraries. Why choose between a monorepo and many repos, when you can have a meta repo?
Meta wraps git and other commands so you can easily execute a single command on all your projects at once, like doing a
git checkout -b feature/new-branch on 30 repos at once.
Most developers, at some point in their careers, work on what they later learn was a monolithic appication. And, typically, they walk away from that experience with a healthy motivation to never build or work on such an app again.
Long before the term 'microservices' got popular, people were building distributed systems. Those who learned to fear monolithic apps were building distributed systems with many services, where each service does one thing and does it well. Often, by making a service do one thing – and only one thing – the complexity of that service would be dramatically reduced, compared to something a bit more monolithic. But the cost of spreading your complexity out amongst simpler parts is to have a bit of complexity in the architecture, itself. The trees are quite easy to see, but the forest starts out a bit fuzzy.
Meta is a plugin-powered tool whose purpose is to make building distributed systems easier. It does so by providing commands which can be
executed against any number of projects in your solution at once. Need to create a branch on five projects at once, commit, and push? start
meta git checkout -b feature/my-new-branch --include-only project1, project2, project3.
Meta was created after years of using an alternative tool, gitslave, to manage very large systems. Gitslave works in much the same way as meta-git's commands. But, gitslave is minimally supported and clunky. Meta started as an attempt to replace gitslave, but quickly turned into something more than just git commands.
Git submodules and git subtree both offer the ability to load child repositories under a parent, but both too have some clunkiness around ensuring updates end up in the correct repository, or that updates indeed make it into yours.
Lerna is the newest kid on the block. Lerna hears the question "Mono repo or many repos?" and says mono. Unfortunately, despite their benefits, monorepos have problems of their own. Eventually, as systems get large enough, different services become owned by different teams and individuals. Over time, it makes less sense to have a single repository define the entire system that runs an organization. Eventually, teams would prefer to run slices of that system. Lerna does not have this capability, but meta does. Meta can allow finer grained access permissions to different parts of your code base. And, with some fancy tricks, meta can still provide all the benefits of a metarepo (think a special branch that contains you child repository files, for the purpose of continuous integration).
Meta is a work in progress. So far just
git status, and
git checkout are implemented:
➜ metaUsage: meta [options] [command]Commands:exec run commands against your meta and child repositoriesgit manage your meta repo and child git repositoriesinit initialize a new meta reponpm run npm commands against your meta and child repositoriesproject add & remove child repositorieshelp [cmd] display help for [cmd]Options:-h, --help output usage information-V, --version output the version number
➜ meta gitUsage: meta-git [options] [command]Commands:checkout checkout a common branch across all repositoriesclone clone meta and child repositoriesstatus git status of meta and child repositorieshelp [cmd] display help for [cmd]Options:-h, --help output usage information
The git functionality above is provided to meta via the meta-git plugin. Meta, itself, actually only implements functionality to load plugins, provide tab completion, and render help text. As such, all functionality comes from plugins.
Want to add functionality to run against your entire system, composed of many repos, all at once? Write a plugin! Plugins follow the git-subcommand pattern of commander.js and implement a single index.js function to apply their top level menu to the bare meta command.
The best way to get started is to do the following:
npm i -g metameta git clone email@example.com:mateodelnorte/meta.gitcd ./metanpm installmeta npm installmeta npm link --allnpm link
This will clone the meta project,
meta, enter the directory, and then use
meta to perform
npm link --all in each directory listed in
projects of the
.meta JSON configuration file, and link meta itself to be used as a global command.
You can then write your command and test using
./bin/meta git gh [subcommand].
You can run the above as a single command:
meta git clone firstname.lastname@example.org:mateodelnorte/meta.git && cd ./meta && npm i && meta npm install && meta npm link --all && npm link
Yarn lovers can do the same:
npm i -g metameta git clone email@example.com:mateodelnorte/meta.gitcd ./metayarnmeta yarn installmeta yarn link --allyarn link
meta git clone firstname.lastname@example.org:mateodelnorte/meta.git && cd ./meta && yarn && meta yarn install && meta yarn link --all && yarn link
See discussion here for more details