Split your monorepo into many repos
Go Shell
Latest commit 2ba6937 Jan 2, 2017 @fabpot fabpot updated LICENSE year


Monolithic Repositories to Many Repositories made easy

tl;dr: splitsh-lite is a replacement for the subtree split Git built-in command that is much faster and has more features at the same time.

When starting a new project, do you store all the code in one monolithic repository? Or are you creating many repositories?

Both strategies work well but both have drawbacks as well. splitsh helps use both strategies at the same time by providing tools that automatically synchronize a mono repository to many repositories.

splitsh-lite is a sub-project with the goal of providing a faster replacement of the git subtree split command.

If you want to learn more about monorepo vs manyrepos, watch this 4-minute lightning talk I gave at dotScale (or read the slides)... or watch the longer version from DrupalCon.

The main splitsh-lite feature is its ability to create a branch in a repository from one or many directories.


Install libgit2:

go get -d github.com/libgit2/git2go
cd $GOPATH/src/github.com/libgit2/git2go
git checkout next
git submodule update --init
make install


go get github.com/splitsh/lite
go build -o splitsh-lite github.com/splitsh/lite

If everything goes fine, a splitsh-lite binary should be available in the current directory.


Let say you want to split the lib/ directory of a repository to its own branch; from the "master" Git repository (bare or clone), run:

splitsh-lite --prefix=lib/

The sha1 of the split is displayed at the end of the execution:

SHA1=`splitsh-lite --prefix=lib/`

The sha1 can be used to create a branch or to push the commits to a new repository.

Automatically create a branch for the split by passing a branch name via the --target option:

splitsh-lite --prefix=lib/ --target=branch-name

If new commits are made on the repository, update the split by running the same command again. Updates are much faster as splitsh-lite keeps a cache of already split commits. Caching is possible as splitsh-lite guarantees that two splits of the same code always results in the same history and the same sha1s for each commit.

By default, splitsh-lite splits the current checkout-ed branch but you can split a different branch by passing it explicitly with --origin (mandatory when splitting a bare repository):

splitsh-lite --prefix=lib/ --origin=origin/1.0

You don't even need to run the command from the Git repository directory if you pass the --path option:

splitsh-lite --prefix=lib/ --origin=origin/1.0 --path=/path/to/repo

Available options:

  • --prefix is the prefix of the directory to split; you can put the split contents in a directory by using the --prefix=from:to syntax; splitting several directories is also possible by passing multiple --prefix options;

  • --path is the path to the repository to split (current directory by default);

  • --origin is the Git reference for the origin (can be any Git reference like HEAD, heads/xxx, tags/xxx, origin/xxx, or any refs/xxx);

  • --target creates a reference for the tip of the split (can be any Git reference like HEAD, heads/xxx, tags/xxx, origin/xxx, or any refs/xxx);

  • --progress displays a nice progress bar during the split;

  • --quiet suppresses all output on stderr (useful when run from an automated script).

  • --scratch flushes the cache (useful when a branch is force pushed or in case of corruption)

  • --git simulates old versions of git subtree split. splitsh generates the same sha1s as the latest version of Git by default (latest). Simulate old versions of Git by using <1.8.2 or <2.8.0.

splitsh provides more features including a sanity checker, GitHub integration for real-time splitting, tagging management and synchronization, and more. It has been used by the Symfony project for many years but the tool is not yet ready for Open-Source. Stay tuned!

If you think that your Open-Source project might benefit from the full version of splitsh, send me an email and I will consider splitting your project for free on my servers (like I do for Symfony and Laravel).