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"
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:
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:
$ 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:
$ 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