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, onmain.upstream/holds three bare upstreams:pkg-a.git,pkg-b.gitandlib-c.git, reached ashttps://git.example.com/<name>.git.monorepo/vendor/pkg-a/is already a splice. Its fetched upstream is one commit ahead.pkg-b.githas not been spliced in yet.monorepo/libs/c/is an ordinary folder whose upstream,lib-c.git, is empty.
Commands
| Command | What it does |
|---|---|
status | Shows each splice's sync state, with how many commits push would publish and pull would bring in. |
clone | Splices an existing repository into a new folder, as one commit. |
fetch | Fetches every branch of each upstream into refs/splices/<key>/heads/. |
log | Shows the commits push would publish and pull would bring in. |
merge | Splices already-fetched upstream changes in, as one ordinary commit per splice. |
pull | fetch + merge. |
diff | Shows the file changes push would send. |
push | Rebuilds the commits that changed each splice since its boundary and pushes them upstream. Writes nothing to the monorepo. |
init | Makes a folder a splice of a new, empty repository. |
boundary | Prints the monorepo commit a splice's rebuild starts from, usually its last sync. |
rebuild | Prints the commit push would send, without pushing it. |
key | Prints 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