{"id":16191219,"url":"https://github.com/simonbaeumer/monorepo-operator","last_synced_at":"2025-11-11T22:07:39.908Z","repository":{"id":64303011,"uuid":"209388908","full_name":"SimonBaeumer/monorepo-operator","owner":"SimonBaeumer","description":"Manage your mono repos with subtree splits.","archived":false,"fork":false,"pushed_at":"2020-02-24T12:02:02.000Z","size":1828,"stargazers_count":12,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T23:01:38.653Z","etag":null,"topics":["continuous-integration","git","golang","monolithic","monorepo","xp"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimonBaeumer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-18T19:33:36.000Z","updated_at":"2024-10-09T21:05:34.000Z","dependencies_parsed_at":"2023-01-15T09:45:22.683Z","dependency_job_id":null,"html_url":"https://github.com/SimonBaeumer/monorepo-operator","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/SimonBaeumer/monorepo-operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonBaeumer%2Fmonorepo-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonBaeumer%2Fmonorepo-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonBaeumer%2Fmonorepo-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonBaeumer%2Fmonorepo-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimonBaeumer","download_url":"https://codeload.github.com/SimonBaeumer/monorepo-operator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimonBaeumer%2Fmonorepo-operator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266963381,"owners_count":24013039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-25T02:00:09.625Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuous-integration","git","golang","monolithic","monorepo","xp"],"created_at":"2024-10-10T07:45:24.236Z","updated_at":"2025-11-11T22:07:39.868Z","avatar_url":"https://github.com/SimonBaeumer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# monorepo-operator\n\nA tool for managing monolithic repositories with subtree splits.\n\n\n## Table of contents\n\n* [Quick start](#quick-start)\n  + [Requirements](#requirements)\n  + [Usage](#usage)\n    - [list](#list)\n    - [clone](#clone)\n    - [sync](#sync)\n    - [exec](#exec)\n    - [add](#add)\n    - [add](#remove-branches)\n    - [project](#project)\n      * [exec](#exec)\n      * [split](#split)\n  + [Configuration](#configuration)\n* [Development](#development)\n  + [Targets](#build-targets)\n  + [ToDo](#todo)\n\n## Quick start\n\nThis tool is for monolithic repository which need to synchronize directories into subtree repos.\nA common use case is maintaining plugins or themes in the same repository.\n\n```\nplugins/\n├── repo01\n└── repo02\n```\n\nThe `init` command create the necessary mappings for your directories. You can find this example in the \n[_examples](_examples) directory. \n\nThe `--operating-dir` flag specifies the directory where the repositories related to the directories will be stored. \nThese will be used for performing batch tasks on all subtrees with the `exec` command.\n\n```bash\n# Initialize the repos with the operating directory \".repos\"\n$ monorepo-operator init --operating-dir=.repos git@github.com:SimonBaeumer plugins/\n\n# View written config file\n$ cat .monorepo-operator.yml\nprojects:\n- name: repo01\n  path: plugins/repo01\n  git-url: git@github.com:SimonBaeumer/repo01.git\n- name: repo02\n  path: plugins/repo02\n  git-url: git@github.com:SimonBaeumer/repo02.git\noperating-directory: .repos\n\n# Clone the repository into the specified operating-directory .repos\n$ monorepo-operator clone\n\u003e Cloning repo01\n\u003e Cloning repo02\n\n$ ls -la .repos/\ntotal 16\ndrwxrwxr-x 4 user user 4096 Okt 22 13:50 .\ndrwxrwxr-x 5 user user 4096 Okt 22 13:44 ..\ndrwxrwxr-x 3 user user 4096 Okt 22 13:50 repo01\ndrwxrwxr-x 3 user user 4096 Okt 22 13:50 repo02\n\n# Execute a command on all subtree-repos directly\n$ monorepo-operator exec \"git remote -v\"\n\u003e Execute on repo01\norigin  git@github.com:SimonBaeumer/repo01.git (fetch)\norigin  git@github.com:SimonBaeumer/repo01.git (push)\n\u003e Execute on repo02\norigin  git@github.com:SimonBaeumer/repo02.git (fetch)\norigin  git@github.com:SimonBaeumer/repo02.git (push)\n```\n\nThey `sync` can only be performed from the root of your monorepo repo. This will not work with the example. \n\n`sync` creates subtrees for each project in the `.monorepo-operator.yml` with the \n`git subtree split` command. After that it pushed the changes to the desired repository, in this case `testing`.\n\n```bash\n# Create subtrees from currently checked out ref and push it to the configured repos on branch testing.\n$ monorepo-sync tesing\n\u003e split project repo01 in branch repo01-testing\n\u003e add remote repo01\n\u003e push project repo01\nCounting objects: 6, done.\n[...]\nTo github.com:SimonBaeumer/repo01\n * [new branch]      repo01-testing -\u003e testing\n\u003e remove remote repo01\n\u003e remove branch repo01-testing\nDeleted branch repo01-testing (was a8f688f).\n\n\u003e split project repo02 in branch repo02-testing\n\u003e add remote repo02\n\u003e push project repo02\nTotal 0 (delta 0), reused 0 (delta 0)\n[...]\nTo github.com:SimonBaeumer/repo02\n * [new branch]      repo02-testing -\u003e testing\n\u003e remove remote repo02\n\u003e remove branch repo02-testing\nDeleted branch repo02-testing (was 8fbf026).\n``` \n\n### Requirements\n\n - git\n - `windows`, `osx` or `linux`\n \n### Usage\n\n#### list\n\n`list` displays an overview of all projects which are managed by the `monorepo-operator`.\n\n```bash\n$ ./monorepo-operator --config _examples/.monorepo-operator.yml list\n+--------+----------------+------------------------------------+\n|  NAME  |      PATH      |              GIT-URL               |\n+--------+----------------+------------------------------------+\n| repo01 | plugins/repo01 | git@github.com:SimonBaeumer/repo01 |\n| repo02 | plugins/repo02 | git@github.com:SimonBaeumer/repo02 |\n+--------+----------------+------------------------------------+\n```\n\n#### clone\n\n`clone` clones all projects into the specified `operating-directory`.\n\n```bash\n# If the operating-directory exists the command fails \n$ monorepo-operator clone\n\u003e Cloning repo01\n2019/10/22 14:05:34 error while cloning: fatal: destination path '.git/.subtree-repos/repo01' already exists and is not an empty directory.\n\n# Overwrite and re-clone all project with the --reset flag\n$ monorepo-operator clone --reset\n\u003e Removing operating directory at .git/.subtree-repos\n\u003e Cloning repo01\n\u003e Cloning repo02\n```\n\n#### sync\n\n`sync` the current branch to a target branch on the remote subtree repositories. \nThis command only works in the root directory of your mono-repo.\n\nIf the `--force` flag is set the `sync` will perform a force push with `git push -f [...]`.\n\nThe `--remove-branches` flag removes branches in subtree repos which do not exist in the mono-repo.\n\nThe `--tags` flag syncs a tag instead of the given branch.  \n\n```bash\n# Sync branches\n$ monorepo-operator sync [branch-name]\n\n# Sync tags\n$ monorepo-operator sync [tag-name] --tags\n```\n\n#### exec\n\n`exec` executes shell commands on all projects.\n\n```bash\n$ monorepo-operator exec \"echo hello\"\n\u003e Execute on project01\nhello\n\u003e Execute on project02\nhello\n```\n\n#### add\n\n`add` adds a new project mapping to the `.monorepo-operator.yml`.\n\n\n```bash\n# Add project to your mapping config\n$ monorepo-operator add repo03 git@github.com:SimonBaeumer/repo03.git repos/\n\u003e Write config file .monorepo-operator.yml\n\n# Directly clone the repo of the project with --clone\n$ monorepo-operator add --clone repo03 git@github.com:SimonBaeumer/repo03.git repos/\n\u003e Write config file .monorepo-operator.yml\n\u003e Cloning repo03\n[...]\n```\n\n#### remove-branches\n\n`remove-branches` removes branches which do not exist locally or on the remote mono-repo in subtree repos.\n\n`--no-local` disables removing local branches which do not exist in the remote mono repo.\n`--no-remote` disables removing remote branches in subtree-repos which do not exist in the remote mono repo.\n\n#### project\n\n`project` lets you execute some commands or tasks on a single project.\n\n##### exec\n\n`project exec [name]` executes shell commands on a project.\n\n```bash\n$ monorepo-operator project exec repo01 \"echo pwd\"\n\u003e Execute on project01\n/tmp/monorepo/.git/.subtree-repos/repo01\n```\n\n##### split\n\n`project split [name]` creates a subtree split of the project and returns the hash of it.\n\n```bash\n$ monorepo-operator project split repo01\n44a603d1720dee64e8c4f5b13f5b5f2e87d54402\n```\n\n### Configuration\n\n```yaml\n# Mapping of projects to path inside the mono-repo and the corresponding git-url\nprojects:\n- name: project01\n  path: projects/project01\n  git-url: git@github.com:UserName/project02.git\n\n- name: project02\n  path: projects/project02\n  git-url: git@github.com:UserName/project02.git\n  \n# Provide regexes for branches which should be excluded if the sync uses force pushes\nprotected:\n  - master\n  - \\d{0,9}\\.\\p{N}\\d{0,9}\\.\\p{N}\\d{0,9}\n\n# operating-directory stores the original repositories with the git configs\n# the exec command executes all commands on all directories located under the operating dir\noperating-directory: .git/.subtree-repos\n```\n\nOptionally you can define a directory which is scanned and creates for every directory a project:\n\n```yaml\nprojects:\n- name: \"{{.DirName}}\"\n  path: projects\n  git-url: git@github.com/UserName/{{.DirName}}.git\n  is-dir: true\n```\n\n## Development\n\n### Build targets\n\n```bash\n# Init dev environment, i.e. git-hooks\n$ make init\n\n# Build project\n$ make build\n\n# Create releases\n$ make release\n\n# Execute unit tests\n$ make tests\n```\n\n### ToDo\n\n - Lock and Unlock projects while executing commands\n - Post and Pre-Hooks\n    - Split\n    - Push\n    - Exec\n - Add pipeline examples\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonbaeumer%2Fmonorepo-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonbaeumer%2Fmonorepo-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonbaeumer%2Fmonorepo-operator/lists"}