Manage Git Remotes Without Losing the Push Path
You will finish with a reliable way to inspect, add, rename and remove Git remotes, and to verify where fetches and pushes will go. 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.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Inspect the remotes before changing anything
Change to the repository you intend to inspect. This is a read-only checkpoint, so it is safe to run even when you are unsure 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 is used to obtain refs; the push URL is where git push origin sends commits. Do not treat the presence of an origin remote as proof that it points to the repository you expect.
Check the resolved URL directly when aliases or multiple URLs may 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. It prints the first URL by default. Add --all if the remote may have more than one URL.
2. Add a remote without fetching
Adding a remote writes repository configuration, but it does not contact the server unless you use -f. Use a name that describes the relationship rather than guessing that every server should be called 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 no branch 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 named main.
For a large repository, git remote add -t main staging URL configures tracking for only the named branch. Use -f only when an immediate network fetch is intended. By default, tags reachable from fetched branches are imported; --no-tags and --tags make that choice explicit.
3. Separate fetch and push URLs deliberately
Sometimes you fetch from a public mirror but push to a writable URL. Set the push URL explicitly, then inspect 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 changes where future pushes go. It does not push anything and it does not change an already-created commit. Before using it, confirm that both URLs refer to the same underlying project. The manual warns against using a push URL for an unrelated publishing repository while fetching another project. In that case, create a second remote instead, so the names make the boundary 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 changing directories or switching 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 documentation for the old name before relying on the rename. Commands such as git fetch staging will now fail because the name no longer exists. To undo this example, run git remote rename review staging, provided the destination name is free.
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 after the target remote branch exists:
$ 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 to a branch that has not been fetched, --auto cannot create the pointer. Fetch that branch first, or set a known local remote-tracking branch explicitly with git remote set-head origin main. Deleting the pointer with git remote set-head origin --delete is reversible by setting it again.
6. Remove a remote or prune stale branches
Removing a remote is local configuration surgery. It deletes that remote's configuration and all of its remote-tracking branches; it does not delete commits from other branches or erase the server:
$ git remote remove review
$ git remote
origin
This is destructive to the local references associated with that remote. Before removing it, save any branch names you still need and check git branch --remotes. There is no built-in undo command. Re-adding the same URL restores the configuration, but remote-tracking branches must be fetched again, and an unreferenced local commit may eventually be collected.
To remove only stale remote-tracking branches while keeping the remote, preview the operation first:
$ git remote prune --dry-run origin
Pruning origin
URL: https://example.com/team/project.git
* [would prune] origin/old-feature
Only run the real prune after checking the list:
$ 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 cause pruning to affect local tags, so read the preview carefully.
Done means
git remote -vshows the expected fetch and push destinations.- New remotes have been fetched only when that network operation was intended.
- Any separate push URL has been checked against the project boundary.
- Renamed remotes have been updated in scripts, hooks and documentation.
- Pruning was previewed first, and a remote was removed only after its local references were no longer needed.