Skip to main content

Scenario: status and push through the tree

A pull goes down the tree: a splice's upstream decides which splices are inside it, so the parent goes first. A push goes up: a parent's upstream has a .splice for each child, which records a commit of the child's upstream. The rebuild of the parent writes into it the rebuild of the child, the commit the child's push sends, so one push --all leaves every upstream recording what the one inside it got from the monorepo, without a commit in the monorepo in between. An upstream that moved on since is pulled first, as before any push. status looks at each splice on its own, and so it can.

Here, the monorepo changed vendor/a/, b/ in it and c/ in that.

Output​

setup.bash builds this state:

$ build_scenario scenario_recursive_pull
$ echo "a in the monorepo" >>vendor/a/file.txt &&
> echo "b in the monorepo" >>vendor/a/b/notes.txt &&
> echo "c in the monorepo" >>vendor/a/b/c/file.txt &&
> git add vendor/a &&
> git commit -q -m "m1: a, b and c in the monorepo"

The tree: the monorepo at m1, outlined orange; vendor/a/ at a1, then dashed m1', outlined orange; b/ at b1, then the same; c/ at c1, then the same; d/ at d1

Status​

Each splice with commits of its own is ahead of its upstream:

$ git splice status
On branch main

ahead 1 vendor/a
ahead 1 vendor/a/b
ahead 1 vendor/a/b/c

up to date vendor/a/d

One push​

Bottom-up, c first. Each rebuild records the one below it, and its push sends that record:

$ git splice push --all
ok vendor/a/b/c: pushed c36e473 to main
ok vendor/a/b: pushed 5302c23 to main
ok vendor/a/d: nothing to push
ok vendor/a: pushed 04ebbea to main

b's upstream records the commit c's upstream has now:

$ git -C "$UPSTREAM-b.git" show main:c/.splice | git config --file - splice.commit | cut -c1-7 &&
> git -C "$UPSTREAM-c.git" rev-parse --short main
c36e473
c36e473

And a's upstream the one b's upstream has:

$ git -C "$UPSTREAM-a.git" show main:b/.splice | git config --file - splice.commit | cut -c1-7 &&
> git -C "$UPSTREAM-b.git" rev-parse --short main
5302c23
5302c23
$ git splice status
On branch main

up to date vendor/a
up to date vendor/a/b
up to date vendor/a/b/c
up to date vendor/a/d

The monorepo keeps its own records: its vendor/a/b/c/.splice still names c1, and each rebuild writes the new commit on the way out. So each splice has the commit it pushed above its synced commit, solid now, as its upstream has it:

The tree after the push: the monorepo at m1; vendor/a/ at a1, then m1', solid: its upstream has it; b/ at b1, then the same; c/ at c1, then the same; d/ at d1

A change in c/ only​

m2 changes only vendor/a/b/c/:

$ echo "c again" >>vendor/a/b/c/file.txt &&
> git commit -q -am "m2: c again"

It's a change in b/ and vendor/a/ too: their folders contain c/, and their record of c/ changes with it. So each of them gets m2' as well. d/ doesn't:

The tree: the monorepo at m2; vendor/a/ at a1, then dashed m2'; b/ at b1, then the same; c/ at c1, then the same; d/ at d1, with nothing of m2

$ git splice push --all
ok vendor/a/b/c: pushed 3830d27 to main
ok vendor/a/b: pushed e99151a to main
ok vendor/a/d: nothing to push
ok vendor/a: pushed a0972a4 to main

The push sends m2' to the three upstreams, bottom-up, and nothing to d's; each m2' is solid now. The records are right again:

The tree after the push: the monorepo at m2; vendor/a/ at a1, then m2', solid; b/ at b1, then the same; c/ at c1, then the same; d/ at d1

$ git -C "$UPSTREAM-b.git" show main:c/.splice | git config --file - splice.commit | cut -c1-7 &&
> git -C "$UPSTREAM-c.git" rev-parse --short main
3830d27
3830d27
$ git -C "$UPSTREAM-a.git" show main:b/.splice | git config --file - splice.commit | cut -c1-7 &&
> git -C "$UPSTREAM-b.git" rev-parse --short main
e99151a
e99151a
$ git splice status
On branch main

up to date vendor/a
up to date vendor/a/b
up to date vendor/a/b/c
up to date vendor/a/d