Fix: fatal: remote origin already exists
Part of: Docker, DevOps & Infrastructure
Quick Answer
How to fix the 'fatal: remote origin already exists' error in Git by updating the remote URL, removing and re-adding origin, managing multiple remotes, and handling forked repos.
When Git Refuses to Add the Same Name Twice
Personally, this is one of the friendliest Git errors because the message tells you exactly what went wrong. The fix is rarely complicated, but the right command depends on whether you want to KEEP the existing remote (update its URL) or REPLACE it (remove and re-add). I have learned to run git remote -v before either move. You run git remote add origin to connect your local repository to a remote, and Git throws:
fatal: remote origin already exists.The full command usually looks like this:
git remote add origin https://github.com/user/repo.gitOr with SSH:
git remote add origin git@github.com:user/repo.gitEither way, Git refuses to add the remote. The error appears in the terminal, in VS Code’s Git integration, in JetBrains IDEs, and in any other tool that wraps Git under the hood.
Quick Reference Before You Dive In
If you arrived here from Google with a fresh error, the five facts that resolve roughly 90 percent of cases:
- Run
git remote -vFIRST. It shows whatorigincurrently points at. The fix differs depending on whether you want to update or replace. Thegit remotedocumentation and the Git Tools - Working with Remotes guide are the canonical sources. git remote set-url origin <new-url>is the right fix in 80 percent of cases. It updates the URL without removing and re-adding, preserving branch tracking.git remote remove origin && git remote add origin <url>is for a CLEAN SLATE. Use when you want to reset everything associated with the remote.- For forks,
originpoints to YOUR FORK andupstreampoints to the ORIGINAL. Never setoriginto the upstream; you do not have push access. - In CI / CD, the script needs to be idempotent. Use
git remote set-url origin <url> || git remote add origin <url>or check existence first.
The rest of this article walks through each cause in detail, plus the failure modes most other guides skip.
How Git Tracks Remote Names
Git remotes are named references to remote repository URLs. When you run git remote add origin <url>, Git tries to create a new remote called origin. If a remote with that name already exists in your repository’s configuration, Git stops and throws the error.
Here are the most common scenarios that lead to this:
You already initialized the remote. You ran git remote add origin earlier in the project, or the repo was cloned from a remote (cloning automatically sets origin to the source URL). Running the command a second time fails because the name is taken.
You cloned the repo. When you git clone a repository, Git automatically creates a remote named origin pointing to the URL you cloned from. If you then try to add origin again (perhaps to point it at a different URL) you get the error.
You re-initialized the repo. You ran git init in a directory that already had a .git folder. The git init command does not remove existing remotes. Your old origin remote survives the reinitialization. If you’re troubleshooting Git not recognizing your repository, be aware that re-running git init does not reset remotes.
You’re following a tutorial. Many tutorials include git remote add origin as a step. If you’ve already done it once (or if you’re restarting the tutorial) the second attempt fails.
A GUI tool or IDE set it up. Tools like GitHub Desktop, VS Code, and JetBrains IDEs often configure remotes automatically when you create or open a project. You may not realize origin already exists.
There is also a subtler cause that affects long-lived repositories. Older Git workflows assumed every contributor would manage origin by hand, while modern hosts and IDEs treat it as a managed setting. When the two collide (for example, a script that ran on Git 2.5 against a repository now opened in a 2024-era IDE) the IDE adds its own origin entry without checking whether one already exists. The conflict surfaces the next time anything runs git remote add.
Version History That Changes the Failure Mode
The exact behavior you see depends heavily on which Git version is installed and which platform conventions the remote uses. The error string has been stable for over a decade, but the surrounding tooling has shifted in ways that change how you should respond.
- Git 2.7 (Jan 2016): introduced
git remote rename, which made it possible to recover from an accidentaloriginwithout removing and re-adding the remote. If you are on anything older, you only haveremove+add. - Git 2.21 (Feb 2019) fixed several edge cases around
git remotein multi-worktree checkouts. Before 2.21, remotes added in one worktree could appear duplicated when listed from another. If you see ghostoriginentries on an older 2.x install, upgrade before debugging further. - Git 2.28 (Jul 2020) added the
init.defaultBranchconfig, the same release in which GitHub announced it would renamemastertomainon new repos by Oct 2020. Many tutorials written between mid-2020 and 2021 mixmasterandmaininterchangeably, which is one reason people end up runninggit remote add origintwice (once for each branch name they expected). - Git 2.30 (Dec 2020) made
mainthe documented default branch in the official docs. Combined with GitHub’s switch, this is when most “remote already exists, but pointing at the wrong URL” reports started appearing in IDEs that auto-detected a fork. - Git 2.41 (Jun 2023) added transparent fetch hints when
originexists with an outdated URL, so agit fetchnow sometimes suggestsset-urlbefore you ever try to re-add. If your Git is older than 2.41, you will not see that hint. - Git 2.43 (Nov 2023) deprecated several
filter-branchpaths and improved howgit remote -vreports per-remote pushURL overrides, which is helpful when a corrupted config produces phantomoriginentries.
If you are unsure what you are running, git --version settles it in one line. Anything older than 2.28 is worth upgrading on its own merits, since most modern tutorials assume main and the newer defaults.
When to Use Which Fix
The next eight sections cover the fixes in detail. The table below maps your situation to the recommended fix.
| Your situation | Recommended fix | Why |
|---|---|---|
Want to point origin at a new URL | Fix 1: git remote set-url origin <url> | Preserves branch tracking |
Want a complete reset of origin | Fix 2: remove + add | Wipes everything cleanly |
| Not sure what’s configured | Fix 3: git remote -v, inspect .git/config | Diagnose first |
| Need a second remote (multi-host, fork) | Fix 4: use a different name (upstream, github) | origin is just one of N |
| Re-initialized repo, old remotes survived | Fix 5: set-url, or remove .git only if truly starting fresh | Re-init does not reset remotes |
| Switching HTTPS ↔ SSH | Fix 6: set-url to the new protocol form | Same URL slot |
| Error in IDE (VS Code, JetBrains) | Fix 7: use IDE remote manager, or open terminal | Same underlying Git |
| CI pipeline keeps failing | Fix 8: make the script idempotent | Pipeline runs many times |
If multiple rows apply, pick the topmost one.
Fix 1: Update the Existing Remote URL
If origin already exists and you want to change where it points, use git remote set-url instead of git remote add:
git remote set-url origin https://github.com/user/new-repo.gitThis overwrites the existing URL without removing and re-adding the remote. It preserves any tracking branch configuration tied to origin.
Verify the change:
git remote -vYou should see:
origin https://github.com/user/new-repo.git (fetch)
origin https://github.com/user/new-repo.git (push)This is the recommended approach in most cases. It is a single command, it does not disrupt your branch tracking, and it avoids the brief window where no remote exists at all.
A pattern I use whenever I switch machines or generate a new SSH key: set-url between HTTPS and SSH forms. The URL slot is the same; only the protocol differs. git remote set-url origin git@github.com:user/repo.git flips to SSH; the same command with the HTTPS form flips back. If you run into authentication issues after switching to SSH, check your SSH key configuration.
Fix 2: Remove the Remote and Re-Add It
If you want a clean slate (or if the existing remote has corrupted configuration) remove it first, then add it fresh:
git remote remove origin
git remote add origin https://github.com/user/repo.gitThe older syntax git remote rm origin also works and does the same thing:
git remote rm origin
git remote add origin https://github.com/user/repo.gitAfter adding, verify:
git remote -vWhen to use this over set-url: Use this approach when you want to reset all configuration associated with the remote, including custom fetch refspecs, push URLs, or per-remote settings. set-url only changes the URL; remove + add wipes everything and starts fresh.
Note: Removing a remote also removes all remote-tracking branches associated with it (origin/main, origin/develop, etc.). They will be recreated the next time you git fetch, but any local configuration referencing them (such as branch tracking) will need to be set up again.
After re-adding the remote, set your branch to track the remote branch:
git branch --set-upstream-to=origin/main mainOr push with the -u flag to set tracking automatically:
git push -u origin mainIf the push is rejected, you may have a non-fast-forward issue that needs resolving separately.
Fix 3: Inspect Your Remotes First
Before changing anything, check what remotes you currently have:
git remote -vThis shows all configured remotes with their fetch and push URLs:
origin https://github.com/user/old-repo.git (fetch)
origin https://github.com/user/old-repo.git (push)You might discover that origin already points to the correct URL. In that case, no fix is needed; you can skip the git remote add step entirely and move on to pushing or pulling.
You can also inspect a specific remote in detail:
git remote show originThis displays the remote URL, the HEAD branch, tracked branches, and the local branches configured for git pull and git push. It is useful for diagnosing mismatched configurations.
If you want to see the raw Git configuration for remotes, check your .git/config file:
cat .git/configLook for sections like:
[remote "origin"]
url = https://github.com/user/repo.git
fetch = +refs/heads/*:refs/remotes/origin/*You can manually edit this file to change or remove remotes, but using git remote commands is safer and less error-prone.
Fix 4: Use a Different Remote Name
You are not limited to the name origin. If you need to add a second remote (for example, to push to a different hosting service) use a different name:
git remote add github https://github.com/user/repo.git
git remote add gitlab https://gitlab.com/user/repo.git
git remote add bitbucket https://bitbucket.org/user/repo.gitThen push to a specific remote by name:
git push github main
git push gitlab mainThis is common when you mirror a repository across multiple platforms or when you want to deploy to different services from the same repo.
Working With Forked Repositories
When you fork a repository on GitHub, a common convention is:
originpoints to your forkupstreampoints to the original repository
If you cloned your fork, origin is already set. Add the original repo as upstream:
git remote add upstream https://github.com/original-owner/repo.gitNow you can pull changes from the original project:
git fetch upstream
git merge upstream/mainOr rebase on top of upstream changes:
git fetch upstream
git rebase upstream/mainIf you accidentally tried to add the original repo as origin (which is already taken by your fork), that is when you hit the “remote origin already exists” error. The fix is to use upstream as the remote name instead.
To verify your setup:
git remote -vExpected output for a forked repo:
origin https://github.com/your-user/repo.git (fetch)
origin https://github.com/your-user/repo.git (push)
upstream https://github.com/original-owner/repo.git (fetch)
upstream https://github.com/original-owner/repo.git (push)A specific fork pattern I have seen junior contributors trip on: setting origin to the upstream (original) repository instead of their fork. Push fails with a permission error because they do not own the upstream. Always: origin = your fork, upstream = the original. Memorize that one pair and you avoid most fork confusion.
Fix 5: Handle Re-Initialized Repositories
If you ran git init in a folder that already had a .git directory, your existing remotes survive. Git prints:
Reinitialized existing Git repository in /path/to/repo/.git/This message tells you the repository was not created fresh. All previous configuration, including remotes, branches, and commit history, remains intact.
If your intent was to start completely fresh, you have two options.
Option A: Remove the .git directory and reinitialize:
rm -rf .git
git init
git remote add origin https://github.com/user/repo.gitWarning: This permanently deletes all Git history, branches, stashes, and configuration. Only do this if you genuinely want to start from scratch.
Option B: Just update the remote:
git remote set-url origin https://github.com/user/new-repo.gitThis keeps your history and branches intact while pointing origin at a new location.
If you accidentally deleted your .git folder and lost your repository, you will need to recover the directory before any remote command can succeed.
Fix 6: Switch Between HTTPS and SSH
A common reason for re-adding origin is switching the protocol. Maybe you set up the repo with HTTPS but now want SSH (or vice versa).
Check the current URL:
git remote -vIf you see an HTTPS URL:
origin https://github.com/user/repo.git (fetch)
origin https://github.com/user/repo.git (push)Switch to SSH:
git remote set-url origin git@github.com:user/repo.gitIf you see an SSH URL and want HTTPS:
git remote set-url origin https://github.com/user/repo.gitHTTPS vs SSH: When to Use Which
Use SSH when:
- You have SSH keys set up and want passwordless pushes
- You work on a machine where you can store keys securely
- You’re tired of entering credentials or dealing with token expiration
Use HTTPS when:
- You’re behind a corporate firewall that blocks SSH (port 22)
- You prefer using a personal access token (PAT) for authentication
- You’re on a shared or temporary machine where storing SSH keys is not ideal
For GitHub specifically, the URL formats are:
| Protocol | URL Format |
|---|---|
| HTTPS | https://github.com/user/repo.git |
| SSH | git@github.com:user/repo.git |
For GitLab:
| Protocol | URL Format |
|---|---|
| HTTPS | https://gitlab.com/user/repo.git |
| SSH | git@gitlab.com:user/repo.git |
For Bitbucket:
| Protocol | URL Format |
|---|---|
| HTTPS | https://bitbucket.org/user/repo.git |
| SSH | git@bitbucket.org:user/repo.git |
Fix 7: Fix the Error in VS Code, JetBrains, or Other IDEs
If you encounter this error in an IDE rather than the terminal, the underlying cause and fix are the same. The IDE is running git remote add origin behind the scenes, and it fails because origin already exists.
VS Code:
- Open the terminal in VS Code (
Ctrl+``orCmd+``on macOS). - Run
git remote -vto see current remotes. - Use
git remote set-url origin <new-url>to update.
Alternatively, edit .git/config directly; VS Code can open it like any other file.
JetBrains (IntelliJ, WebStorm, PyCharm, etc.):
- Go to Git > Manage Remotes (or VCS > Git > Remotes in older versions).
- You’ll see the existing
originremote listed. - Click the pencil icon to edit the URL, or the minus icon to remove it.
GitHub Desktop:
- Go to Repository > Repository Settings.
- The primary remote URL is shown under Remote.
- Change the URL and click Save.
In all cases, the fix is the same: update the existing origin URL rather than trying to add a new one.
Fix 8: Handle CI/CD Pipeline Errors
This error can appear in CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins, etc.) when a script tries to add a remote that already exists. Pipelines typically clone the repo, which sets origin automatically.
Make your pipeline script idempotent by checking if the remote exists before adding it:
if git remote get-url origin >/dev/null 2>&1; then
git remote set-url origin "$REPO_URL"
else
git remote add origin "$REPO_URL"
fiOr use a simpler one-liner that removes first (ignoring errors if it does not exist) and then adds:
git remote remove origin 2>/dev/null; git remote add origin "$REPO_URL"This pattern prevents the error from breaking your pipeline regardless of the repository state.
Stranger Causes I Have Tracked Down
If the fixes above did not resolve your issue, try these less obvious solutions:
Check for a corrupted .git/config file. Open .git/config in a text editor and look for duplicate [remote "origin"] sections or malformed entries. Remove duplicates manually and save. If the file is severely corrupted, you may need to clone the repo fresh.
Check for nested Git repositories. If you have a .git directory inside another Git repository’s subdirectory, you may be running commands in the wrong context. Run git rev-parse --show-toplevel to confirm which repository root you’re operating in.
Check if you’re in a detached HEAD state. A detached HEAD does not directly cause the “remote origin already exists” error, but it can create confusion about which branch and remote you’re working with. Make sure you’re on the correct branch before modifying remotes.
Verify file system permissions. On Linux/macOS, if the .git/config file is read-only or owned by a different user, Git may fail in unexpected ways. Check permissions with ls -la .git/config and fix with chmod or chown if needed.
Re-clone as a last resort. If nothing else works and your remote configuration is completely mangled, the simplest fix is to re-clone:
cd ..
mv repo repo-backup
git clone https://github.com/user/repo.gitCopy any uncommitted work from repo-backup into the fresh clone. This gives you a clean .git directory with properly configured remotes.
Check for Git LFS issues. If you’re using Git LFS and seeing additional errors alongside the remote issue, the remote configuration problem might be preventing LFS from communicating with the server. Fix the remote first, then address any LFS-related errors separately.
Check for a stale credential helper entry. macOS osxkeychain and Windows manager-core cache credentials per remote URL. If you switched accounts but the helper still hands the old token to the new origin, Git can behave as if the remote was never fully reset. Clear the entry with git credential reject and the protocol+host pair, then re-add the remote so a fresh token is requested.
Check for insteadOf URL rewrites. A global url.<base>.insteadOf rule (often added by corporate proxies or gh setup) rewrites your remote URL on every command. If you see git remote -v showing one URL but pushes go somewhere else, run git config --get-regexp '^url\.' and remove or scope the rewrite. The rewrite alone does not cause “remote origin already exists,” but it can make the underlying repository state genuinely confusing.
Check whether a submodule shadowed the remote. If git remote add origin runs inside a directory that is also a submodule of a parent repo, Git may resolve .git to the submodule’s .git file (a pointer into .git/modules/<name> in the parent). Adding origin there is valid, but the next time the parent reinitializes the submodule, your remote can appear “already” set. Run git rev-parse --git-dir to see exactly which directory Git is editing.
What Other Tutorials Get Wrong About This Error
Most Git tutorials list the same fixes but frame them in ways that produce subtle bugs.
They jump to remove + add for everything. git remote set-url preserves branch tracking and per-remote configuration; remove + add wipes it. Articles that recommend the destructive form for every case create extra setup work.
They miss the fork convention. origin should point to YOUR fork, upstream to the original. Tutorials that show forks but recommend setting origin to the upstream send junior contributors into permission errors when they try to push.
They omit IDE remote managers. VS Code, JetBrains, and GitHub Desktop all have UI for editing remotes. Articles that show only terminal commands miss that most IDE users prefer the UI.
They miss insteadOf URL rewrites. A global url.<base>.insteadOf rule silently rewrites URLs at every git command. Tutorials that focus only on the in-repo .git/config miss that the rewrite happens at the user-config level.
They confuse git init with a reset. Re-running git init does NOT reset remotes; it just reinitializes the directory. Tutorials that show git init as a recovery step send readers to the wrong tool.
They miss CI idempotency. Pipeline scripts must handle both “remote exists” and “remote does not exist” gracefully. Tutorials that show one-shot commands without the idempotent pattern break CI for the second run.
Frequently Asked Questions
What is the difference between set-url and remove + add?
set-url changes only the URL while preserving branch tracking, custom fetch refspecs, and other per-remote configuration. remove + add deletes all of that and starts fresh. Use set-url when you want to point at a new URL with the same setup; use remove + add when you want a clean reset.
Why does my forked repo need both origin and upstream?
origin points to your personal fork (where you push). upstream points to the original repository (where you pull updates from). Without upstream, you cannot easily sync your fork with the original; without origin, you cannot push your changes.
Can I rename origin to something else?
Yes: git remote rename origin <new-name> (Git 2.7+). This is useful when you want a more descriptive name (github, production, etc.) or when you want to free up the origin name for a different repository.
Does git init reset my remotes?
No. Re-running git init in a directory that already has a .git folder reinitializes the directory but preserves all existing configuration including remotes. The message “Reinitialized existing Git repository” tells you nothing was reset. To actually reset, delete .git/ and re-run git init.
Why does my CI script keep hitting this error?
The CI runs git remote add origin <url> on every job. The first job creates origin; the second job fails because it already exists. Make the script idempotent: git remote set-url origin <url> 2>/dev/null || git remote add origin <url>.
Can I see what was previously configured?
Look at .git/config directly. The [remote "<name>"] sections show each configured remote with its URL and fetch refspec. Editing the file by hand works but is error-prone; prefer git remote commands.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Git Worktree Not Working — Branch Already Checked Out, Prune, Submodules, and Locked Worktrees
How to fix git worktree errors — fatal: 'branch' is already checked out at, worktree prune removing valid trees, detached HEAD on add, submodules not initialized, moving/locking worktrees, and ignoring per-worktree files.
Fix: Undo git reset --hard and Recover Lost Commits
How to undo git reset --hard and recover lost commits using git reflog — step-by-step recovery for accidentally reset branches, lost work, and dropped stashes.
Fix: .gitignore Not Working (Files Still Being Tracked)
How to fix .gitignore not working — files still showing in git status after being added to .gitignore, caused by already-tracked files, wrong syntax, nested gitignore rules, and cache issues.
Fix: git fatal: A branch named 'x' already exists
How to fix 'git fatal: A branch named already exists' when creating or renaming branches — including local conflicts, remote tracking branches, and worktree issues.