Skip to main content

Scenario: after-pull

A pull merged local commits that were never pushed. The pull's commit is the newest that changed .splice, but the rebuild starts further back, at B: the newest such commit whose folder is the upstream commit it recorded, U(B) (sync model). The commits are named as in the drawing there.

Output​

setup.bash builds this state:

$ build_scenario scenario_after_pull

The graphs after a pull: the pull commit e records n, so U(H) = n; B stays at a, and U(B) = k; R is e prime, a merge of the rebuilt d prime and n

The monorepo:

$ git log --format=%s
e
d
c
b
a
initial commit
$ git -C "$UPSTREAM" log --format='%h %s' main
df79a48 n
d34c417 m
5ba0fc7 l
ae8b31f k

U(H)​

e is the newest commit that changed .splice. It records n as U(H):

$ git log --first-parent -1 --format=%s -- lib/.splice
e
$ git log -1 --format='%h %s' "$(git config --file lib/.splice splice.commit)"
df79a48 n

B​

But e's folder isn't n: it has b's and d's files too, which the upstream lacks. A rebuild starting at e would send them as one commit, under e's message:

$ git diff --stat "$(git config --file lib/.splice splice.commit)" HEAD:lib -- ':!.splice'
b.txt | 1 +
d.txt | 1 +
2 files changed, 2 insertions(+)

So the rebuild goes back to the commit before e that changed .splice. All of them, newest first:

$ git log --first-parent --format=%s -- lib/.splice
e
a

a's folder is the commit it recorded, k. It's HEAD~4:

$ k="$(git config --blob 'HEAD~4:lib/.splice' splice.commit)" &&
> git diff --quiet "$k" HEAD~4:lib -- ':!.splice' &&
> echo "a's folder is k"
a's folder is k

So a is B, what git splice boundary prints, and U(B) = k:

$ git log -1 --format=%s "$(git splice boundary lib)"
a

The commits since B that change the folder are the ones the rebuild copies, newest first:

$ git log --first-parent --format=%s "$(git splice boundary lib)"..HEAD -- lib
e
d
b

R​

From B, the rebuild copies b and d on top of U(B) = k, as b' and d', and skips c. Then it copies e as e', a merge of d' and n, with e's message. log --graph draws R and T down to n, where they meet. k shows up as the parent of b':

$ git splice log --graph lib
=== lib (main)
< 8430dba (R) e (Test <test@example.com>)
|\
< | d4da194 d (Test <test@example.com>)
< | 9ec734f b (Test <test@example.com>)
o | ae8b31f k (Test <test@example.com>)
/
o df79a48 (T) n (Test <test@example.com>)

After the push​

The push sends b', d' and e', and T moves to e':

$ git splice push lib
ok lib: pushed 8430dba to main

A pull right after it has nothing to bring in, and leaves .splice as it was. So B is still a: every rebuild still walks from a, and rebuilds b', d' and e' with the same hashes.

$ git splice pull lib
ok lib fetched
ok lib: nothing to pull
$ git log -1 --format=%s "$(git splice boundary lib)"
a

After a bump​

git splice pull --bump records e' as U(H), in a new commit:

$ git splice pull --bump -m f lib
ok lib fetched
ok lib: bumped the synced commit to 8430dba

Its folder is e', so it's the new B, U(B) = e', and rebuilds start there (pushed draws this state):

$ git log -1 --format=%s "$(git splice boundary lib)"
f