Upstreams
An upstream is much like a Git remote: a named repository a splice fetches
from and pushes to. Its name and URL live inside the splice folder, in
.splice, so they move and branch with it
(why):
[upstream "origin"]
url = https://git.example.com/s.git
Unlike a Git remote, it is fetched into private refs without creating an
entry under git remote
(why).
A fork and the original
A common use for several upstreams is working with a company fork while still fetching the original:
[splice]
default-upstream = fork
[upstream "origin"]
url = https://git.example.com/lib.git
[upstream "fork"]
url = https://git.example.com/company/lib.git
When .splice names several upstreams, default-upstream says which one
commands use when --upstream is omitted. Without it, commands that need
one upstream refuse to guess. In the example above, commands use fork
unless --upstream origin selects the original; fetch fetches both
(example).
URLs, keys and refs
Each named upstream in .splice has a URL. The monorepo uses that URL as
the upstream's identity.
A key is a short, ref-friendly nickname for one unique upstream URL. The
mapping is one-to-one within the monorepo: one URL has one key, and one key
names one URL. For example, https://github.com/acme/shared-lib.git gets
the key shared-lib, so its main branch is fetched to
refs/splices/shared-lib/heads/main.
The first fetch records the mapping and fetches the upstream's branches to
refs/splices/<key>/heads/. These are ordinary Git refs, so commands such
as git log can read them and git worktree add can check them out
(example).
Choosing a key
The generated key comes from the URL, but it can be renamed. Choose a name you already associate with the upstream, or one that makes its refs easier to recognize and type.
upstreams-setup.bash builds an example whose generated key is s.
Rename it to shared-lib through any splice that uses the URL:
$ git splice key app-a/s shared-lib
ok app-a/s: renamed key 's' to 'shared-lib'
The refs move with the key:
$ git for-each-ref --format='%(objectname:short) %(refname)' refs/splices
bde4164 refs/splices/shared-lib/heads/main
Because a key belongs to its URL, the rename applies to every splice that names that URL.
Tracking another upstream branch locally
A splice normally syncs with the upstream branch that corresponds to the current monorepo branch. When their names deliberately differ, track the upstream branch to use instead, much like setting a Git branch's upstream:
$ git splice fetch --branch development --track app-a/s
ok app-a/s fetched
ok app-a/s: 'main' tracks 'development' from now on
The override is local to this clone and the current monorepo branch. It is
stored by upstream key, so it applies to every splice using that upstream.
Plain sync and status commands use it from then on. Stop using it with
--no-track:
$ git splice fetch --no-track app-a/s
ok app-a/s fetched
ok app-a/s: 'main' no longer tracks 'development'
See the fetch command reference for the other
ways to set a tracked branch and its exact fallback behavior.
The same library at different versions
In the same example, app-a/ and app-b/ each contain their own splice
of the library s. Both .splice files name the same upstream URL:
$ git config --file app-a/s/.splice upstream.origin.url
https://git.example.com/s.git
$ git config --file app-b/s/.splice upstream.origin.url
https://git.example.com/s.git
Both therefore report the key chosen above:
$ git splice key app-a/s
shared-lib
$ git splice key app-b/s
shared-lib
They still choose versions independently. Pulling a new upstream commit
into app-a/s leaves app-b/s behind:
$ seed_bare_repo "$UPSTREAM" "upstream change" &&
> git splice pull app-a/s >/dev/null &&
> git splice status
On branch main
behind 1 app-b/s
up to date app-a/s
The two folders are independent splices because they have different
ids.