Skip to main content

Walkthrough

Let's start with an example monorepo and three upstreams. The walkthrough uses the same sandbox throughout, under $WALKTHROUGH:

  • monorepo/ is the working repository, on main.
  • upstream/ holds three bare upstreams: pkg-a.git, pkg-b.git and lib-c.git, reached as https://git.example.com/<name>.git.
  • monorepo/vendor/pkg-a/ is already a splice. Its fetched upstream is one commit ahead.
  • pkg-b.git has not been spliced in yet.
  • monorepo/libs/c/ is an ordinary folder whose upstream, lib-c.git, is empty.

Commands​

CommandWhat it does
statusShows each splice's sync state, with how many commits push would publish and pull would bring in.
cloneSplices an existing repository into a new folder, as one commit.
fetchFetches every branch of each upstream into refs/splices/<key>/heads/.
logShows the commits push would publish and pull would bring in.
mergeSplices already-fetched upstream changes in, as one ordinary commit per splice.
pullfetch + merge.
diffShows the file changes push would send.
pushRebuilds the commits that changed each splice since its boundary and pushes them upstream. Writes nothing to the monorepo.
initMakes a folder a splice of a new, empty repository.
boundaryPrints the monorepo commit a splice's rebuild starts from, usually its last sync.
rebuildPrints the commit push would send, without pushing it.
keyPrints the key of a splice's upstream, or renames it, refs included.

clone, init, fetch, merge, pull, push, status, diff and log are named after Git's commands, and do to a splice what their namesakes do to a repository. boundary, rebuild and key are new: their names come from splicing.

Each of them only runs the git command line, and Git can list what it ran.

merge, pull and push need paths or --all; status, diff, log and fetch cover every splice unless you name some (why). status, diff, log and merge only use what was last fetched. With several upstreams, --upstream <name> picks one. Run git splice <command> --help for options.

status​

Lists every splice with its sync state (status in detail):

$ git splice status
On branch main

behind 1 vendor/pkg-a

clone​

Splices in pkg-b (clone in detail):

$ git splice clone https://git.example.com/pkg-b.git vendor/pkg-b
=== vendor/pkg-b: fetching https://git.example.com/pkg-b.git
ok vendor/pkg-b: cloned 9b3cb02 from main

fetch​

Someone pushes to pkg-b's upstream. fetch fetches every splice's upstream in parallel and calls out which branch moved (fetch in detail):

$ git clone -q "$WALKTHROUGH/upstream/pkg-b.git" ../pkg-b &&
> echo "pkg-b: add a feature" >>../pkg-b/file.txt &&
> git -C ../pkg-b commit -qam "pkg-b: add a feature" &&
> git -C ../pkg-b push -q
$ git splice fetch
ok vendor/pkg-a fetched
ok vendor/pkg-b fetched (main moved 9b3cb02..b937c4f)

log​

> marks what a pull brings in, < what a push publishes (log in detail):

$ git splice log
=== vendor/pkg-a (main)
> 703b936 pkg-a: a second commit, after the clone (Walkthrough <walkthrough@example.com>)
=== vendor/pkg-b (main)
> b937c4f pkg-b: add a feature (Walkthrough <walkthrough@example.com>)

merge​

Splices in what was fetched, without contacting the upstream (merge in detail):

$ git splice merge vendor/pkg-a
ok vendor/pkg-a: merged 703b936

pull​

fetch and merge in one (pull in detail):

$ git splice pull --all
ok vendor/pkg-a fetched
ok vendor/pkg-b fetched
ok vendor/pkg-a: nothing to pull
ok vendor/pkg-b: pulled b937c4f

diff​

A commit in the monorepo changes vendor/pkg-a/. diff shows what push would send, with paths as the upstream sees them (diff in detail):

$ echo "a local fix" >>vendor/pkg-a/file.txt && git commit -qam "pkg-a: a local fix"
$ git splice diff --stat
=== vendor/pkg-a
file.txt | 1 +
1 file changed, 1 insertion(+)

push​

Sends it to the upstream branch named like yours (push in detail):

$ git splice push --all
ok vendor/pkg-a: pushed 2d02eb8 to main
ok vendor/pkg-b: nothing to push
$ git splice status
On branch main

up to date vendor/pkg-a
up to date vendor/pkg-b

init​

Makes libs/c/ a splice of the empty lib-c.git; the first push publishes it (init in detail):

$ git splice init libs/c https://git.example.com/lib-c.git
ok libs/c: initialized -- 'git splice push libs/c' publishes it
$ git splice push libs/c
?? libs/c: upstream has no 'main' branch yet -- this push creates it
ok libs/c: pushed 9dc1e6a to main

boundary​

The monorepo commit vendor/pkg-a/'s rebuild starts from, here its last sync (boundary in detail):

$ git show -s --oneline "$(git splice boundary vendor/pkg-a)"
6dbb42b splice: merge vendor/pkg-a from main at 703b936

rebuild​

The commit push would send (rebuild in detail):

$ git show -s --oneline "$(git splice rebuild vendor/pkg-a)"
2d02eb8 pkg-a: a local fix

key​

The short name of vendor/pkg-a/'s upstream in refs/splices/ (key in detail):

$ git splice key vendor/pkg-a
pkg-a