fatal: tag 'v1.0' already exists means the tag name is taken in your
repository; ! [rejected] v1.0 -> v1.0 (already exists) means it is taken
on the remote. To move the tag to a new commit, use git tag -f v1.0 locally
and git push --force origin v1.0 for the remote, or, usually better, tag
the fix with a new version number.
A plain push did not move the existing tag on the remote, and a clone that already had
the old v1.0 kept it on both git fetch and
git fetch --tags. If the tag was already published, a new
tag such as v1.0.1 avoids two people meaning different commits by the same
name.
The error
Creating the tag again locally:
PS> git tag v1.0
fatal: tag 'v1.0' already exists
Pushing a moved tag to a remote that already has it:
PS> git push origin v1.0
To ..\b6-remote.git
! [rejected] v1.0 -> v1.0 (already exists)
error: failed to push some refs to '..\b6-remote.git'
hint: Updates were rejected because the tag already exists in the remote.
Why it happens
A tag is a name for one commit, meant to stay put. git tag NAME creates the
name and refuses (exit code 128) when it exists, so it never silently moves a release
marker. The push has the same rule: the remote already holds v1.0 pointing
at the old commit, and a push may not change an existing tag without being forced.
The usual story: you tag v1.0, push it, find a last-minute bug, commit the
fix and want v1.0 to include it. The local git tag v1.0 fails
first; after git tag -f the local tag moves, and then the push fails.
The fix
Move the tag locally, then force that one tag on the remote:
PS> git tag -f v1.0
Updated tag 'v1.0' (was 8e0e663)
PS> git push --force origin v1.0
To ..\b6-remote.git
+ 8e0e663...b79ea5f v1.0 -> v1.0 (forced update)
PS> git ls-remote --tags origin
b79ea5f6beeed52482484cc0be9546397c2263c9 refs/tags/v1.0
PS> git rev-parse v1.0
b79ea5f6beeed52482484cc0be9546397c2263c9
git ls-remote shows the remote tag now points at the same commit as the
local one. Naming the tag in the push (origin v1.0) keeps the force to that
single ref. Teammates who already have the old v1.0 keep it: in a clone
made before the tag moved, git fetch --tags refused the new one until it
was forced:
PS> git fetch --tags
From C:/.../b6-remote
! [rejected] v1.0 -> v1.0 (would clobber existing tag)
PS> git fetch --tags --force
From C:/.../b6-remote
t [tag update] v1.0 -> v1.0
After the tag moved once more, a plain git fetch in the same clone exited 0,
updated origin/main, and left the local v1.0 on the old commit
(7addd6e) while the remote's pointed at c432b2b, with no
warning at all.
That is why a new version tag is the friendlier choice once a release is public.
How it was reproduced
Git for Windows 2.45.2 on Windows 11, Windows PowerShell 5.1, in a throwaway repository
with a local bare repository as origin. v1.0 was created and
pushed; after a further commit, git tag v1.0 exited with 128, and after
git tag -f v1.0 the push exited with 1. git push --force origin
v1.0 updated the remote tag, confirmed with git ls-remote --tags.
Frequently asked
- How do I move an existing git tag to another commit?
- Run git tag -f with the tag name on the commit you want, then git push --force origin with the tag name to update the remote.
- Why is my git tag push rejected with already exists?
- The remote already has a tag of that name pointing at a different commit, and a normal push does not change existing tags. Force that tag, or use a new tag name.
- Should I move a release tag or create a new one?
- Create a new one when the old tag has already been pushed and others may have fetched it. After a move, existing clones keep the old tag; their git fetch --tags is rejected with would clobber existing tag until they add --force.
More decoded errors in the Fixes category. When a branch push is rejected rather than a tag, see git push rejected (non-fast-forward).