Package: git-ws
Documentation-PyPI-Sources-IssuesGit Workspace - Multi Repository Management ToolInstallationUsageGetting StartedCheat-SheetPython APIAlternativesGit Workspace is a lightweight tool for creating and managingworkspacesconsisting of several interdependentgitrepositories. Starting from amain repository, Git Workspace 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.📦 InstallationGit Workspace is written in Python.RecommendedPlease install python and then try:curl-Lhttps://github.com/pypa/pipx/releases/latest/download/pipx.pyz-opipx.pyz&&python3pipx.pyzinstallgit-wsMaybe you need run:python3pipx.pyzensurepathviapipxIf you already installedpipx(https://pypa.github.io/pipx/installation/) just run:pipxinstallgit-wsMaybe you need run:pipxensurepathviapippipinstallgit-wsAnd that's it! Ideally, if your project also uses Python, we recommend adding Git Workspace 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 Git Workspace as a development dependency:poetryadd--groupdevgit-wsFor testing you can try:gitws--version📔 UsageGit Workspace is integrated into gitgit ws- this is what you will be using most of the time.The ManifestLet's assume we have a project calledmyapp, which requires a librarymylibthat is maintained in anothergitrepository. In order to use this project with Git Workspace,myappneeds to provide a so calledmanifest. A Git Workspace manifest is a simpleTOMLfile - by default calledgit-ws.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), then 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 using the same protocol for the main repository as well as any of its dependencies.See theManifest Documentationfor any further details on available options.The Initial CloneTo build a workspace from a project prepared like that, simply clone it viagit ws:cd$HOME/Projects
gitwsclone--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-amyapp/# Should print something like.
..
.git-ws
myapp
mylibAs you can see, besides the two repositories we wanted, there is also a hidden.git-wsfolder where the tool stores the needed configuration data.Thegit ws clonedocumentationdescribes all options.InitializationSometimes there are use cases where usinggit ws clonecannot be used. For example, when you set up your manifest for the first time or 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 followingwithinthe main project:gitwsinit--update👉 As withgit ws clone, without the--update, no dependencies will be fetched.This command initializes the workspace and just needs to run once.
Changes to the manifest require an update operation (see next section) but no re-initialization.UpdatingAnother important use case is keeping a workspace up-to-date. Let's 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):gitwsupdate# Alternatively, run `git rebase` instead of `git pull` in dependencies:gitwsupdate--rebaseNon-Git Main Projectsgit wscan leave the manifest version control to any other version control system (Subversion, VCS, DesignSync, etc.).
Just manage the manifest filegit-ws.tomlwithin the version control system of your choice.
Rungit ws init --updateorgit ws init --update -M path/to/git-ws.tomlin the intended workspace directory.👉 As before, without the--update, no dependencies will be fetched.Insidea git clone,git ws inituses the current git project as themain projectof the workspace.Outsidea git clone,git ws initinitializes a workspacewithoutamain project.👉 There are just two drawbacks of a workspace without a main project:git ws taghas no main project to tag and will fail. Please usegit ws manifest freeze.Relative URLs are not supported, as there is no URL to be relative to. Please useremotes:[[remotes]]name="main"url-base="git@github.example.com:your-group"[[dependencies]]name="dep1"remote="main"👍 Getting StartedPlease ensure a properinstallation.Lets take a clone of an example project, which does not usegit wsyet.mkdir-p$HOME/Projects/Example-Workspacecd$HOME/Projects/Example-Workspace
gitclonehttps://github.com/c0fec0de/git-ws-example-one.git# Cloning into 'git-ws-example-one'...# remote: Enumerating objects: 3, done.# remote: Counting objects: 100% (3/3), done.# remote: Compressing objects: 100% (2/2), done.# remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0# Receiving objects: 100% (3/3), done.Now you should have one git clone in your workspace directory. Let's use it asmain project.
At first, we need a manifest filegit-ws.toml.cdgit-ws-example-one
gitwsmanifestcreate# Manifest 'git-ws.toml' created.gitaddgit-ws.tomlNow, we need to initialize the workspacegitwsinit# ===== . (MAIN 'git-ws-example-one') =====# Workspace initialized at '..'.# Please continue with:##     git ws update#The parent directory became thegit wsworkspace directory.
The current git clone is themain projectnow.git wssuggests to rungit ws update.
You can try, but nothing will happen yet, as the manifest is quite empty.Let's add our first dependencygit-ws-example-lib, which is located on the same git server.
You can manually edit the manifest filegit-ws.toml, or you just rungitwsdepaddgit-ws-example-libFeel free to inspect thegit-ws.tomlfile.git ws updatewill now apply the manifest changes and pull the new dependency:gitwsupdate# ===== . (MAIN 'git-ws-example-one', revision='main') =====# Pulling branch 'main'.# Already up to date.# ===== ../git-ws-example-lib ('git-ws-example-lib') =====# WARNING: Clone git-ws-example-lib has no revision!# Cloning 'https://github.com/c0fec0de/git-ws-example-lib.git'.# Cloning into '../git-ws-example-lib'...# remote: Enumerating objects: 3, done.# remote: Counting objects: 100% (3/3), done.# remote: Compressing objects: 100% (2/2), done.# remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0# Receiving objects: 100% (3/3), done.Please note the warning:# WARNING: Clone git-ws-example-lib has no revision!It is strongly recommended to specify a default revision for all dependencies. The commandgitwsdefaultrevisionmainsolves that for you. Any successivegit ws updateis now free of this warning:===== . (MAIN 'git-ws-example-one', revision='main') =====
Pulling branch 'main'.
Already up to date.
===== ../git-ws-example-lib ('git-ws-example-lib', revision='main') =====
Pulling branch 'main'.
Already up to date.Now you can add, commit and push your changes to thegit-ws.tomlfile.
Other colleagues should use now:cd$HOME/Projects
gitwsclone--updateYOUR-REPO-URL# ORcd$HOME/Projects/Workspace
gitcloneYOUR-REPO-URLcd<directory>
gitwsinit--updategit ws statusshows all changes within all git clones in the workspace.git ws addruns likewise thegit addoperation in the associated git clones.
Please see the next section for an overview of all commands.🕹️ Cheat-SheetInitializationCommandDescriptiongit ws clone URLClone git repository fromURLas main repository and initialize Git Workspacegit ws init(insidea git clone)Initialize Git Workspace at parent directory. Use current git clone as main repositorygit ws init(outsidea git clone)Initialize Git Workspace at current directory. No main repository.git ws manifest createCreate well documented, empty manifestBasicCommandDescriptiongit ws updatePull latest changes on main repository and all dependent repositories (clone them if needed)git ws update --rebaseSame as above, but fetch and rebase instead of pullgit ws statusRungit statuson all repositories (displayed paths include the current clone path)git ws add FILESRungit add FILEonFILESin the corresponding repositoriesgit ws reset FILESRungit reset FILEonFILESin the corresponding repositories. Undogit addgit ws commit FILES -m MESSAGERungit commit FILEonFILESin the corresponding repositoriesgit ws commit -m MESSAGERungit commitrepositories with changesgit ws checkout FILESRungit checkout FILEonFILESin the corresponding repositoriesgit ws checkoutCheckout git revision specified as in the manifest(s) (clone them if needed)Run Commands on all repositoriesCommandDescriptiongit ws pushRungit pushon all repositories (in reverse order)git ws fetchRungit fetchon all repositoriesgit ws rebaseRungit rebaseon all repositoriesgit ws pullRungit pullon all repositoriesgit ws diffRungit diffon all repositoriesgit ws git CMDRungit CMDon all repositoriesgit ws foreach CMDRunCMDon all repositoriesOtherCommandDescriptiongit ws dep update -rUpdate all manifest files, use current checkout branch, tag or SHA asrevision, use current remoteoriginasurl, try to use relative URLs.git ws manifest freezePrint The Resolved Manifest With SHAs For All Project Revisions.git ws manifest pathPrint Path to Main Manifest File.git ws manifest pathsPrint Paths to ALL Manifest Files.git ws manifest resolvePrint The Manifest With All Projects And All Their Dependencies.git ws manifest upgradeUpdate Manifest To Latest Version.git ws manifest validateValidate The Current Manifest, Exiting With An Error On Issues.git ws info main-pathPrint Path to Main Git Clone.git ws info project-pathsPrint Paths to all git clones.git ws info workspace-pathPrint Path to Workspace.git ws info dep-treePrint Dependency Tree.git ws info dep-tree --dot | dot -Tpng > dep-tree.pngDraw Dependency Diagram (needsgraphviz)See thecommand-line interface documentationfor any further details.🐍 Python APIGit Workspace is written in Python. Besides thegit wscommand 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 Git Workspace, we investigated several other existing tools in the hope they would fulfil our 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 start our own tool for the purpose?And that's what we did - Git Workspace is our tool for managing a large workspace consisting of several smallergitprojects. Here is how it compares to the other tools we evaluated:git submodulesrepowestMonoreposgit wsReusable Components✅✅✅➖✅Ease of Use➖✅✅✅✅Editable Components➖✅➖✅✅Freezing Configurations✅✅✅✅✅Transitive Dependencies➖➖✅➖✅Relative Dependency Paths✅✅➖➖✅Branches in dependencies➖✅✅➖✅Symlink/Copyfile-Support➖✅➖➖✅👉 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 on 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 intoWhy We Started Git Workspace.