A tool for managing monolithic repositories with subtree splits.
This tool is for monolithic repository which need to synchronize directories into subtree repos. A common use case is maintaining plugins or themes in the same repository.
plugins/
├── repo01
└── repo02
The init command create the necessary mappings for your directories. You can find this example in the
_examples directory.
The --operating-dir flag specifies the directory where the repositories related to the directories will be stored.
These will be used for performing batch tasks on all subtrees with the exec command.
# Initialize the repos with the operating directory ".repos"
$ monorepo-operator init --operating-dir=.repos git@github.com:SimonBaeumer plugins/
# View written config file
$ cat .monorepo-operator.yml
projects:
- name: repo01
path: plugins/repo01
git-url: git@github.com:SimonBaeumer/repo01.git
- name: repo02
path: plugins/repo02
git-url: git@github.com:SimonBaeumer/repo02.git
operating-directory: .repos
# Clone the repository into the specified operating-directory .repos
$ monorepo-operator clone
> Cloning repo01
> Cloning repo02
$ ls -la .repos/
total 16
drwxrwxr-x 4 user user 4096 Okt 22 13:50 .
drwxrwxr-x 5 user user 4096 Okt 22 13:44 ..
drwxrwxr-x 3 user user 4096 Okt 22 13:50 repo01
drwxrwxr-x 3 user user 4096 Okt 22 13:50 repo02
# Execute a command on all subtree-repos directly
$ monorepo-operator exec "git remote -v"
> Execute on repo01
origin git@github.com:SimonBaeumer/repo01.git (fetch)
origin git@github.com:SimonBaeumer/repo01.git (push)
> Execute on repo02
origin git@github.com:SimonBaeumer/repo02.git (fetch)
origin git@github.com:SimonBaeumer/repo02.git (push)They sync can only be performed from the root of your monorepo repo. This will not work with the example.
sync creates subtrees for each project in the .monorepo-operator.yml with the
git subtree split command. After that it pushed the changes to the desired repository, in this case testing.
# Create subtrees from currently checked out ref and push it to the configured repos on branch testing.
$ monorepo-sync tesing
> split project repo01 in branch repo01-testing
> add remote repo01
> push project repo01
Counting objects: 6, done.
[...]
To github.com:SimonBaeumer/repo01
* [new branch] repo01-testing -> testing
> remove remote repo01
> remove branch repo01-testing
Deleted branch repo01-testing (was a8f688f).
> split project repo02 in branch repo02-testing
> add remote repo02
> push project repo02
Total 0 (delta 0), reused 0 (delta 0)
[...]
To github.com:SimonBaeumer/repo02
* [new branch] repo02-testing -> testing
> remove remote repo02
> remove branch repo02-testing
Deleted branch repo02-testing (was 8fbf026).- git
windows,osxorlinux
list displays an overview of all projects which are managed by the monorepo-operator.
$ ./monorepo-operator --config _examples/.monorepo-operator.yml list
+--------+----------------+------------------------------------+
| NAME | PATH | GIT-URL |
+--------+----------------+------------------------------------+
| repo01 | plugins/repo01 | git@github.com:SimonBaeumer/repo01 |
| repo02 | plugins/repo02 | git@github.com:SimonBaeumer/repo02 |
+--------+----------------+------------------------------------+clone clones all projects into the specified operating-directory.
# If the operating-directory exists the command fails
$ monorepo-operator clone
> Cloning repo01
2019/10/22 14:05:34 error while cloning: fatal: destination path '.git/.subtree-repos/repo01' already exists and is not an empty directory.
# Overwrite and re-clone all project with the --reset flag
$ monorepo-operator clone --reset
> Removing operating directory at .git/.subtree-repos
> Cloning repo01
> Cloning repo02sync the current branch to a target branch on the remote subtree repositories.
This command only works in the root directory of your mono-repo.
If the --force flag is set the sync will perform a force push with git push -f [...].
The --remove-branches flag removes branches in subtree repos which do not exist in the mono-repo.
The --tags flag syncs a tag instead of the given branch.
# Sync branches
$ monorepo-operator sync [branch-name]
# Sync tags
$ monorepo-operator sync [tag-name] --tagsexec executes shell commands on all projects.
$ monorepo-operator exec "echo hello"
> Execute on project01
hello
> Execute on project02
helloadd adds a new project mapping to the .monorepo-operator.yml.
# Add project to your mapping config
$ monorepo-operator add repo03 git@github.com:SimonBaeumer/repo03.git repos/
> Write config file .monorepo-operator.yml
# Directly clone the repo of the project with --clone
$ monorepo-operator add --clone repo03 git@github.com:SimonBaeumer/repo03.git repos/
> Write config file .monorepo-operator.yml
> Cloning repo03
[...]remove-branches removes branches which do not exist locally or on the remote mono-repo in subtree repos.
--no-local disables removing local branches which do not exist in the remote mono repo.
--no-remote disables removing remote branches in subtree-repos which do not exist in the remote mono repo.
project lets you execute some commands or tasks on a single project.
project exec [name] executes shell commands on a project.
$ monorepo-operator project exec repo01 "echo pwd"
> Execute on project01
/tmp/monorepo/.git/.subtree-repos/repo01project split [name] creates a subtree split of the project and returns the hash of it.
$ monorepo-operator project split repo01
44a603d1720dee64e8c4f5b13f5b5f2e87d54402# Mapping of projects to path inside the mono-repo and the corresponding git-url
projects:
- name: project01
path: projects/project01
git-url: git@github.com:UserName/project02.git
- name: project02
path: projects/project02
git-url: git@github.com:UserName/project02.git
# Provide regexes for branches which should be excluded if the sync uses force pushes
protected:
- master
- \d{0,9}\.\p{N}\d{0,9}\.\p{N}\d{0,9}
# operating-directory stores the original repositories with the git configs
# the exec command executes all commands on all directories located under the operating dir
operating-directory: .git/.subtree-reposOptionally you can define a directory which is scanned and creates for every directory a project:
projects:
- name: "{{.DirName}}"
path: projects
git-url: git@github.com/UserName/{{.DirName}}.git
is-dir: true# Init dev environment, i.e. git-hooks
$ make init
# Build project
$ make build
# Create releases
$ make release
# Execute unit tests
$ make tests- Lock and Unlock projects while executing commands
- Post and Pre-Hooks
- Split
- Push
- Exec
- Add pipeline examples