Skip to content

Instantly share code, notes, and snippets.

@aSapien
Last active August 13, 2018 07:26
Show Gist options
  • Save aSapien/b1f69ab86340f10955ea4314c109f021 to your computer and use it in GitHub Desktop.
Save aSapien/b1f69ab86340f10955ea4314c109f021 to your computer and use it in GitHub Desktop.
[Working with a monorepo in isolated subrepos] A way to mimic a multi-repo git environment inside a single monorepo #monorepo #git #trick

Clone a monorepo as isolated subrepos

Motivation & Goal

When working on a monorepo, we often create uncommitted changes in multiple "subrepos", which turns into a mess when preparing a commit, when pulling changes from remote, etc...

Git allows us to create a sparse-clone of the monorepo, containing only the subrepo that we are interested in, yet keeping the integrity and functions of a VCS.

For example, we have a monorepo with the following structure (computer@user:~$ tree monorepo):

.
├── subrepo1
│   ├── file1
│   └── file2
└── subrepo2
    └── file2
    
2 directories, 3 files

The goal is to be able to work seperately (git-wise) on subrepo1 and subrepo2. i.e having 2 clones, monoclone1 for subrepo1 and monoclone2 for subrepo2 with an isolated git status:

First for module subrepo1 (~$ tree monoclone1):

.
└── subrepo1
    ├── file1
    └── file2
    
1 directory, 2 files

Second for modele subrepo2 (~$ tree monoclone2):

.
└── subrepo2
    └── file2

1 directory, 1 file

Creating a monorepo clone, containing an isolated subrepo:

  1. Create a folder for your local copy of the subrepo: mkdir subrepo1 && cd subrepo2

  2. Initialize it as a Git repo and enable Sparse Checkout: git init && git config core.sparseCheckout true

  3. Tell Git which directories you want it to checkout (this is a persistent {.gitignore} syntax file): echo "subrepo1" >> .git/info/sparse-checkout

  4. Add the original repo as a remote url: git remote add origin git@github.com:USER/MONOREPO.git

  5. Pull the master branch from remote: git pull origin master

  6. Set the remote as the default upstream (must complete previous step first): git branch --set-upstream-to=origin/master master

  7. That's it! You can repeat the steps for every seperate submodule that you'd like to isolate.

Useful shell function (source)

Add to .zshrc or .bash_profile

function git_sparse_clone() (
  rurl="$1" localdir="$2" && shift 2

  mkdir -p "$localdir"
  cd "$localdir"

  git init
  git remote add -f origin "$rurl"

  git config core.sparseCheckout true

  # Loops over remaining args
  for i; do
    echo "$i" >> .git/info/sparse-checkout
  done

  git pull origin master
)

Usage:

git_sparse_clone "git@github.com:USER/MONOREPO.git" "./local/location" "subrepo1"

Appendix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment