Package: anyrepo
Multi Repository Management ToolInstallationUsageCheat-SheetPython APIAlternativesAnyRepo is a lightweight tool for creating and managingworkspacesconsisting of several interdependentgitrepositories. Starting from amain repository, AnyRepo discovers dependencies specified in amanifest file, fetching any specified required repositories and assembling them into a single workspace.👉 You can read more about the usednomenclaturein thedocumentation.📦 InstallationAnyRepo is written in Python and - as usual - installing it is pretty easy:pipinstallanyrepoAnd that's it! Ideally, if your project also uses Python, we recommend adding AnyRepo as a dependency to it as well, so that you can track the exact version of it together with your other dependencies. For example, if you usepoetry, add it by running# Add AnyRepo as development dependency:poetryadd--groupdevanyrepo📔 UsageAnyRepo comes with a command line client calledanyrepo- this is what you will be using most of the time.Let's assume we have a project calledmyapp, which requires a librarymylibthat is maintained in anothergitrepository. In order to use this project with AnyRepo,myappneeds to provide a so calledmanifest. An AnyRepo manifest is a simpleTOMLfile - by default calledanyrepo.tomlin the project's root folder - which defines the dependencies a project has as well as some other meta information. A minimal manifest for our project could look like this:[[dependencies]]name="mylib"url="git@github.com:example/mylib.git"revision="v2.3.4"Ifmyappandmylibare stored on the same server (side-by-side), than the manifest can even be simpler:[[dependencies]]name="mylib"revision="v2.3.4"The project will be searched via a relative path (which is either../mylibor../mylib.gitdepending on the main repository's URL). Relative paths are in general useful as they allow to use the same protocol for the main repository as well as any of its dependencies.To build a workspace from a project prepared like that, simply clone it viaanyrepo:cd$HOME/Projects
mkdirmy_app_workspacecdmy_app_workspace
anyrepoclone--updategit@github.com:example/myapp.git👉 Without the--updateoption, only the main repository will be fetched.The above will clone the app repository and also the library side-by-side:ls-a# Should print something like# . .. .anyrepo myapp mylibAs you can see, besides the two repositories we wanted, there is also a hidden.anyrepofolder where the tool stores the needed configuration data.Sometimes there are use cases where usinganyrepo clonecannot be used. For example, when a CI/CD system creates the initial clone of the main repository, you may need a way to fetch the remaining projects. This can be done by simply running the following within the main project:anyrepoinit--update👉 As withanyrepo clone, without the--update, no dependencies will be fetched.Another important use case is keeping a workspace up-to-date. Lets say you pull in an update in the main repository, which in turn might cause changes in the manifest to be pulled in as well. Updating the existing workspace is as simple as# Update the workspace (main and all dependent repositories):anyrepoupdate# Alternatively, run `git rebase` instead of `git pull` in dependencies:anyrepoupdate--rebaseCheat-SheetCommandDescriptionanyrepo clone URLClone git repository fromURLas main repository and initialize AnyRepo workspaceanyrepo initInitialize AnyRepo workspace. Use existing git clone as main repositoryanyrepo manifest createCreate well documented, empty manifestanyrepo updatePull latest changes on main repository and all dependent repositories (and clone them if needed)anyrepo update --rebaseSame as above, but fetch and rebase insteadanyrepo statusRungit statuson all repositories (displayed paths include the actual clone path)anyrepo add FILESRungit add FILEonFILESin the corresponding repositoriesanyrepo reset FILESRungit reset FILEonFILESin the corresponding repositories. Undogit addanyrepo commit FILES -m MESSAGERungit commit FILEonFILESin the corresponding repositoriesanyrepo checkout FILESRungit checkout FILEonFILESin the corresponding repositoriesanyrepo checkoutCheckout git revision specified as specified in the manifestsanyrepo pushRungit pushon all repositoriesanyrepo fetchRungit fetchon all repositoriesanyrepo rebaseRungit rebaseon all repositoriesanyrepo pullRungit pullon all repositoriesanyrepo diffRungit diffon all repositoriesanyrepo git CMDRungit CMDon all repositoriesanyrepo foreach CMDRunCMDon all repositoriesanyrepo manifest freezePrint The Resolved Manifest With SHAs For All Project Revisionsanyrepo manifest resolvePrint The Manifest With All Imports Resolved🐍 Python APIAnyRepo is written in Python. Besides theanyrepocommand line tool, there is also an API which you can use to further automate workspace creation and maintenance. If you are interested, have a look into theAPI documentation.🤝 AlternativesBefore writing AnyRepo, we investigates several other existing tools in the hope they would fulfil out needs. In particular, we looked into the following tools and methodologies which are widely used to organize large projects:git submodules.Google'srepotool.Thewesttool developed in the scope ofZephyr.Leaving the puregitdomain, one can also use a package manager likeconan.And lastly, there are also approaches to still pack everything into a large so calledmonorepo.Unfortunately, none of the tools we tested really satisfied us. But hey, as we are developers -why not starting our own tool for the purpose?And that's what we did - AnyRepo is a our tool for managing a large workspace consisting of several smallergitprojects. Here is how it compares to the other tools we evaluated:git submodulesrepowestMonoreposAnyRepoReusable Components✅✅✅➖✅Ease of Use➖✅✅✅✅Editable Components➖✅➖✅✅Freezing Configurations✅✅✅✅✅Transitive Dependencies➖➖✅➖✅Relative Dependency Paths✅✅➖➖✅👉 Please note that our view on the various features might be biased. As we did, always look at all the options available to you before deciding for one tool or the other. While the other tools in comparison did not model what we needed for our workflow, they might just be what you are looking for.If you want to learn more, have a look into thedocumentation.