# Named Remotes and Multi-Remote Workflows For pushing to a single remote (the common case), see `references/PUSH.md`. This file covers everything else: managing named remotes, selecting which remote to push to, tracking remote bookmarks, and the two canonical multi-remote setups. ## Named remotes When a repo has more than one remote (e.g. `origin` = your fork, `upstream` = the canonical source), you select the target with `--remote `. ```bash jj git remote list # See all remotes and their URLs jj git remote add upstream # Add a second remote jj git remote rename origin fork # Rename a remote jj git remote set-url origin # Change a remote's URL jj git remote remove old-name # Remove a remote (and forget its bookmarks) ``` **Default remote selection**: when `--remote` is omitted, `jj git push` uses: 1. The `git.push` config setting (if set), or 2. The remote named `origin` (if multiple remotes exist), or 3. The single remote (if only one exists) There is **no built-in option to push to multiple remotes in one command** — call `jj git push` once per remote. ### Pushing the same bookmark to two remotes ```bash jj bookmark move my-feature --to @ # Move the bookmark to current change jj git push -b my-feature --remote fork # Push to your fork jj git push -b my-feature --remote upstream # Push to canonical (e.g. for a PR target branch) ``` ### Setting a default remote To avoid typing `--remote` repeatedly: ```bash # Per-repo (writes to .jj/repo/config.toml) jj config set --repo git.push fork # Globally (writes to ~/.config/jj/config.toml) jj config set --user git.push origin ``` ### Tracking a remote bookmark By default, when you `jj git fetch`, remote bookmarks appear as `@` (e.g. `main@upstream`). To get a local bookmark that follows it: ```bash jj bookmark track main@upstream # Track upstream/main as a local 'main' jj bookmark track 'glob:release/*@upstream' # Track all upstream release branches ``` Once tracked, `jj git push --tracked --remote upstream` will push all tracked bookmarks back to that remote. ### Fetching from a specific remote ```bash jj git fetch --remote upstream # Fetch only from upstream jj git fetch --all-remotes # Fetch from every configured remote ``` ### When a push is rejected If the remote has moved since your last fetch, `jj git push` refuses (similar to `git push --force-with-lease`). Re-sync first: ```bash jj git fetch --remote # Pull the remote's current state # (resolve any bookmark conflicts or rebase if needed) jj git push -b --remote # Try again ``` ### Quick reference | Action | Command | |---|---| | List remotes | `jj git remote list` | | Add a remote | `jj git remote add ` | | Push to specific remote | `jj git push -b --remote ` | | Push all tracked bookmarks to a remote | `jj git push --tracked --remote ` | | Set default push remote (repo) | `jj config set --repo git.push ` | | Track a remote bookmark | `jj bookmark track @` | | Fetch one remote | `jj git fetch --remote ` | | Fetch all remotes | `jj git fetch --all-remotes` | ## Common multi-remote workflows Two canonical setups documented in [the jj docs](https://docs.jj-vcs.dev/latest/guides/multiple-remotes/). Pick the one that matches your relationship to the remotes; the config is one-time per repo. **Nomenclature** (jj convention): - `origin` = a remote you have write access to (typically where you push) - `upstream` = the more canonical / well-known repo (you may not have push access) - Trunk is assumed to be `main`, so remote bookmarks are `main@origin` and `main@upstream` ### Scenario 1: GitHub-style fork contributing upstream `upstream` is the canonical project; `origin` is your fork; you open PRs from `origin` against `upstream`. Typical actions: - Fetch from `upstream` to get the latest changes - Push `main` to `origin` to keep your fork's `main` in sync - Push `my-feature` to `origin`, then open a PR targeting `upstream` One-time setup: ```bash # Fetch from both remotes when you run `jj git fetch` jj config set --repo git.fetch '["upstream", "origin"]' # Default push target is your fork jj config set --repo git.push origin # Track both remote bookmarks named `main` jj bookmark track main # Make upstream's main the trunk (treated as immutable; rebases stop here) jj config set --repo 'revset-aliases."trunk()"' main@upstream ``` Why these specifically: - Tracking `main@upstream` keeps your local `main` updated whenever you fetch from upstream - Tracking `main@origin` means `jj git push` will also update your fork's `main` - `trunk() = main@upstream` prevents jj from rewriting commits that are already in the canonical repo ### Scenario 2: Independent repository, periodically integrating from upstream `origin` is a long-lived repository with its own divergent history; `upstream` is the source you occasionally pull changes from but don't contribute back to. Typical actions: - Fetch from `origin` to get the latest of your own work - Push bookmarks to `origin`; merge PRs into `main@origin` - Periodically fetch from `main@upstream` and merge/rebase/duplicate its changes into `main@origin` One-time setup: ```bash # Fetch only from origin (typical case) jj config set --repo git.fetch '["origin"]' # Or fetch from both if you want upstream changes visible on every fetch: # jj config set --repo git.fetch '["upstream", "origin"]' # Default push target is origin jj config set --repo git.push origin # Track only origin's main — do NOT track upstream's main jj bookmark track main --remote=origin jj bookmark untrack main --remote=upstream # Your origin defines the trunk (your main is the canonical line) jj config set --repo 'revset-aliases."trunk()"' main@origin ``` Why these specifically: - Tracking only `main@origin` keeps `main@upstream` as a clearly separate reference you can `rebase`/`merge` from intentionally — it won't silently overwrite your local `main` - `trunk() = main@origin` treats your divergent line (not upstream's) as the immutable history boundary ### Choosing between the scenarios | Question | Scenario 1 | Scenario 2 | |---|---|---| | Do you push features back to upstream as PRs? | Yes | No | | Should fetching from upstream update your local `main`? | Yes | No (you integrate manually) | | Is `upstream/main` immutable from your repo's perspective? | Yes | No (you may rewrite when integrating) | | Is `origin/main` allowed to diverge from `upstream/main`? | Minimally (just for syncing) | Yes (it's the point) |