Scenario: several-upstreams
A library with two upstreams: the third-party original, and the company's fork of it, which carries a patch of its own. The monorepo works with the fork, and takes the original's releases through it (#107).
- Original (
$UPSTREAM, reached ashttps://git.example.com/lib.git):seed. - Fork (
$UPSTREAM-fork.git, reached ashttps://git.example.com/company/lib.git): a copy of the original, thenfork patch. - Monorepo:
vendor/a/, cloned from the original atseed.
Output
setup.bash builds this state:
$ build_scenario scenario_several_upstreams https://git.example.com/lib.git
Adding the fork
A .splice names its upstreams like Git names remotes. The fork is one
more [upstream] section, and since the splice now has two,
default-upstream says which one commands use unless --upstream names
another:
$ git config --file vendor/a/.splice upstream.fork.url https://git.example.com/company/lib.git
$ git config --file vendor/a/.splice splice.default-upstream fork
$ git commit -q -m "vendor/a: work with the company fork" -- vendor/a/.splice
$ cat vendor/a/.splice | tr '\t' ' '
[splice]
commit = bde416459fbcc09c9b585f3b65a94cab3f68bfcd
id = c7ecd5a4c78d8a27
default-upstream = fork
[upstream "origin"]
url = https://git.example.com/lib.git
[upstream "fork"]
url = https://git.example.com/company/lib.git
The synced commit stays one per splice: a sync point is a commit, whichever upstream it came from. A fork shares the original's history, so either can continue from it.
Fetching both
fetch fetches every upstream of the splice, each under its own key:
$ git splice fetch
ok vendor/a fetched from origin
ok vendor/a fetched from fork
$ git config --get-regexp '^splice\.'
splice.lib.url https://git.example.com/lib.git
splice.company-lib.url https://git.example.com/company/lib.git
A splice with several upstreams names its upstream branch as
<name>/<branch>, like origin/main in Git. The default one is the
fork, which has the patch:
$ git splice status
On branch main
behind 1 vendor/a -> fork/main
--upstream compares with the original instead:
$ git splice status --upstream origin
On branch main
up to date vendor/a -> origin/main
$ git splice pull vendor/a
ok vendor/a fetched from fork
ok vendor/a: pulled 9bf41c7
Now the folder has the fork's patch, which the original lacks. A push to the original would contribute it:
$ git splice status --upstream origin
On branch main
ahead 1 vendor/a -> origin/main
Taking a release of the original
The original moves on:
$ seed_bare_repo "$UPSTREAM" "original release" main release.txt
$ git splice fetch --upstream origin
ok vendor/a fetched from origin (main moved bde4164..3fd09f0)
$ git splice status --upstream origin
On branch main
ahead 1, behind 1 vendor/a -> origin/main
$ git splice pull --upstream origin vendor/a
ok vendor/a fetched from origin
ok vendor/a: pulled 3fd09f0
The pull joins the release with the fork's patch, as git pull would.
The fork lacks the release and the join, so a plain push sends them to
the fork:
$ git splice status
On branch main
ahead 2 vendor/a -> fork/main
$ git splice push vendor/a
ok vendor/a: pushed 3a54571 to fork/main
$ git -C "$UPSTREAM-fork.git" log --graph --format=%s main
* splice: pull vendor/a from origin/main at 3fd09f0
|\
| * original release
* | fork patch
|/
* seed
$ git splice status
On branch main
up to date vendor/a -> fork/main