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:
- Monorepo (
vendor/a/): cloned at k in a, then b and d change the folder, c changes another one.git splice pullthen merges n in, as e. - Upstream: k, then l, m and n. It has never seen b or d.
Output
setup.bash builds this state:
$ build_scenario scenario_after_pull
The drawing shows what Git and git-splice say about it. a and e aren't
subjects the drawing can show, so they're named by their place in the
history (check_drawing):
$ check_drawing "$TESTDIR/after-pull.drawio.svg" a=HEAD~4 e=HEAD
ok after-pull.drawio.svg: 12 commits, 17 arrows, 6 boxes, 2 frames
The monorepo, with e on top. a is the clone, add vendor/a:
$ git log --format=%s
splice: pull vendor/a from main at df79a48
d
c
b
add vendor/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 -- vendor/a/.splice
splice: pull vendor/a from main at df79a48
$ git log -1 --format='%h %s' "$(git config --file vendor/a/.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 vendor/a/.splice splice.commit)" HEAD:vendor/a -- ':!.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 -- vendor/a/.splice
splice: pull vendor/a from main at df79a48
add vendor/a
a's folder is the commit it recorded, k. It's HEAD~4:
$ git diff --quiet "$(git config --blob 'HEAD~4:vendor/a/.splice' splice.commit)" HEAD~4:vendor/a -- ':!.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 vendor/a)"
add vendor/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 vendor/a)"..HEAD -- vendor/a
splice: pull vendor/a from main at df79a48
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 vendor/a
=== vendor/a (main)
< 854864a (R) splice: pull vendor/a from main at df79a48 (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 vendor/a
ok vendor/a: pushed 854864a 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 vendor/a
ok vendor/a fetched
ok vendor/a: nothing to pull
$ git log -1 --format=%s "$(git splice boundary vendor/a)"
add vendor/a
After a bump
git splice pull --bump records e' as U(H), in a new commit:
$ git splice pull --bump vendor/a
ok vendor/a fetched
ok vendor/a: bumped the synced commit to 854864a
Its folder is e', so it's the new B, U(B) = e', and rebuilds start there (pushed-and-bumped draws this state):
$ git log -1 --format=%s "$(git splice boundary vendor/a)"
splice: bump vendor/a from main at 854864a