Home / Alt manpages / git-remote(1)

  • git-remote(1)
  • User command
  • linux

Manage Git Remotes Without Losing the Push Path

Half the "why did my push go to the wrong place" panics trace back to a remote nobody checked. This guide gets you inspecting, adding, renaming and removing Git remotes properly, and confirming where fetches and pushes actually land before you trust them.

The examples match Git 2.43.0 from the installed git-man package (Debian package version 1:2.43.0-1ubuntu7.3). Allow about ten minutes. You need an existing Git working tree or repository; none of these commands needs sudo.

1. Inspect the remotes before changing anything

Change to the repository you intend to inspect. This is read-only, so run it even when you are not sure which directory you are in:

$ cd /path/to/project
$ git remote -v
origin  https://example.com/team/project.git (fetch)
origin  https://example.com/team/project.git (push)

The name on the left is the remote name, commonly origin. The two URLs are not necessarily the same. The fetch URL pulls refs; the push URL is where git push origin actually sends commits. An origin remote existing is not proof it points where you expect.

Check the resolved URL directly when aliases or multiple URLs might be involved:

$ git remote get-url origin
https://example.com/team/project.git
$ git remote get-url --push origin
https://example.com/team/project.git

get-url expands Git's insteadOf and pushInsteadOf rules and prints the first URL by default. Add --all if the remote may carry more than one.

2. Add a remote without fetching

Adding a remote writes repository configuration only; it does not touch the network unless you pass -f. Name it for the relationship rather than defaulting everything to origin:

$ git remote add staging https://example.com/team/project-staging.git
$ git remote -v
origin   https://example.com/team/project.git (fetch)
origin   https://example.com/team/project.git (push)
staging  https://example.com/team/project-staging.git (fetch)
staging  https://example.com/team/project-staging.git (push)

At this point nothing has been downloaded from staging. Fetch explicitly when you are ready:

$ git fetch staging
$ git branch --remotes
  origin/main
  staging/main

Your branch names and fetch output will differ. A remote-tracking branch such as staging/main is local information about a branch seen on the remote; it is not the same thing as a local branch called main.

  • Large repository? git remote add -t main staging URL tracks only the named branch.
  • Use -f deliberately. It triggers an immediate network fetch, so only add it when you mean it.
  • Tags come along by default. Anything reachable from fetched branches is imported unless you set --no-tags or --tags explicitly.

3. Separate fetch and push URLs deliberately

Sometimes you fetch from a public mirror but push to a writable URL elsewhere. Set the push URL explicitly, then check both directions:

$ git remote set-url --push origin ssh://[email protected]/team/project.git
$ git remote -v
origin  https://example.com/team/project.git (fetch)
origin  ssh://[email protected]/team/project.git (push)
$ git remote get-url origin
https://example.com/team/project.git
$ git remote get-url --push origin
ssh://[email protected]/team/project.git

This only changes where future pushes go. It does not push anything and does not touch a commit you have already made. Confirm first that both URLs refer to the same project: the manual specifically warns against pointing a push URL at an unrelated publishing repository while fetching another one. If the two are genuinely different projects, use a second remote so the boundary stays visible.

Warning

An incorrect push URL is a security and data-integrity problem. A successful git push can publish private work to the wrong account or repository. Run git remote -v immediately before a sensitive push, especially after switching directories or credentials.

4. Rename a remote, then update scripts

Renaming updates the remote's configuration and its remote-tracking branch names. It does not rename local branches:

$ git remote rename staging review
$ git remote -v
origin  https://example.com/team/project.git (fetch)
origin  https://example.com/team/project.git (push)
review  https://example.com/team/project-staging.git (fetch)
review  https://example.com/team/project-staging.git (push)
$ git branch --remotes
  origin/main
  review/main

Search hooks, aliases, CI configuration and docs for the old name before you trust the rename. git fetch staging will now fail outright because the name is gone. To undo this example, run git remote rename review staging, as long as that name is free again.

5. Set a remote's default branch only after fetching it

The remote HEAD is a symbolic local pointer such as refs/remotes/origin/HEAD. It lets commands use origin where they would otherwise need origin/main. Set it automatically once the target branch actually exists locally:

$ git fetch origin
$ git remote set-head origin --auto
origin/HEAD set to main
$ git symbolic-ref --short refs/remotes/origin/HEAD
origin/main

If the remote's advertised HEAD points at a branch you have not fetched, --auto cannot create the pointer. Fetch that branch first, or set a known remote-tracking branch explicitly with git remote set-head origin main. Deleting the pointer with git remote set-head origin --delete is reversible: just set it again.

6. Remove a remote or prune stale branches

Removing a remote is local configuration surgery. It deletes that remote's configuration and every remote-tracking branch it owns; it does not delete commits on other branches or touch the server:

$ git remote remove review
$ git remote
origin

This is destructive to the local references tied to that remote and there is no built-in undo. Before removing it, save any branch names you still need and check git branch --remotes. Re-adding the same URL restores the configuration, but remote-tracking branches must be fetched again, and an unreferenced local commit can eventually be garbage-collected.

To clear only stale remote-tracking branches while keeping the remote, preview first:

$ git remote prune --dry-run origin
Pruning origin
URL: https://example.com/team/project.git
 * [would prune] origin/old-feature

Only run it for real once the list looks right:

$ git remote prune origin
Pruning origin
URL: https://example.com/team/project.git
 * [pruned] origin/old-feature

Pruning removes stale references, not the remote's server-side branches and not your local branches. Configuration can also make pruning touch local tags, so read the preview before you commit to it.

Done means

  • git remote -v shows the destinations you expect. Fetch and push URLs both check out.
  • New remotes were only fetched on purpose. No surprise network calls.
  • A separate push URL was checked against the project boundary. Not an unrelated repository.
  • Renamed remotes are updated everywhere. Scripts, hooks and docs, not just your terminal.
  • Pruning was previewed first. A remote was only removed once its references were no longer needed.