--- topic: remotes source_keys: - git-scm-remote-docs - git-scm-fetch-docs - git-scm-push-docs - git-scm-pull-docs --- ## `set-url` — full form ```bash git remote set-url # replace the first fetch URL git remote set-url # replace only the URL matching regex git remote set-url --push # change push URL only (must point at same repo) git remote set-url --add # add an extra push URL (push to multiple remotes) git remote set-url --delete # remove URLs matching regex ``` `--push` changes only where pushes go — fetch and push URLs must still reference the same repository. For genuine fetch-from-A / push-to-B workflows, use two separate named remotes instead. ## Shallow clones and partial fetch ```bash git fetch # fetch one branch only, stored in FETCH_HEAD (not a local/tracking ref) git fetch --depth= # deepen history, or create a shallow clone git fetch --unshallow # convert a shallow clone to full history git fetch --update-shallow # allow the fetch to update the shallow boundary git fetch --refmap='' # fetch without updating any tracking ref (FETCH_HEAD only) ``` ## Default fetch refspec The default fetch refspec is `+refs/heads/*:refs/remotes//*`. The leading `+` forces the update — remote-tracking branches always mirror the remote exactly and provide no protection for local history. Fetch never touches your local branches, only remote-tracking refs. ## Force-push safety — full detail `--force-with-lease` rejects the push if the remote ref moved since your last fetch. Three forms: | Form | What it protects | |---|---| | `--force-with-lease` (bare) | All refs being pushed, checked against your remote-tracking branch | | `--force-with-lease=` | Named ref only | | `--force-with-lease=:` | Named ref must be at exact SHA — most stable | **Caveat with the bare form:** any background process that runs `git fetch` (IDE plugin, cron job, editor auto-fetch) updates your remote-tracking branch, which can make the lease check pass even though someone else pushed in between. The protection is silently defeated. Two mitigations: ```bash # Option 1 — dedicated push-only remote: background tools fetch `origin`, you push # through a separate remote that nothing else touches, so its tracking ref can't be # poisoned by an unrelated fetch. git remote add origin-push $(git config remote.origin.url) git push --force-with-lease origin-push # Option 2 — explicit SHA via a local tag, unaffected by tracking-branch state git fetch git tag base master git rebase -i master git push --force-with-lease=master:base master:master ``` `--force-if-includes` adds a second check on top of bare `--force-with-lease`: it verifies the remote-tracking tip actually appears in your local branch's reflog, i.e. you genuinely integrated it before rewriting. It is a no-op without `--force-with-lease`, and has no effect when the `--force-with-lease=:` form is used (that form already pins an exact SHA). Safest combination: `git push --force-with-lease --force-if-includes origin`. Remote-side policies (`receive.denyDeletes`, `receive.denyDeleteCurrent`, `receive.denyNonFastForwards`) are enforced server-side regardless of any local flag — a server configured this way rejects the push even with `--force`. ## Pull config precedence Highest wins: 1. Command-line flag (`--ff-only` / `--rebase` / `--no-rebase`) 2. `pull.rebase` config (global or local) 3. `branch..rebase` (branch-specific override) 4. `branch.autoSetupRebase` (set automatically when the tracking branch was created) ```bash git config --global pull.rebase true git config branch.develop.rebase false # develop always merges, regardless of the global default ```