Safeguard
Supply Chain•

What happens when a maintainer moves a git tag you already pulled?

Git does not silently change a tag you already have. You can end up with two different things called the same version, so pin by commit hash.

Safeguard Security Team
4 min read

Your copy of the tag stays pointing at the old commit. Git does not change tags behind your back, so you and the maintainer can hold different code under the same version name. To be sure what you build, record and pin the commit hash, not just the tag.

What the git manual says

The git-tag documentation has a section on re-tagging. If someone tagged the wrong commit and has not pushed anything, they can simply re-tag with the force option. If they have pushed, others will already have seen the old tag, and the manual gives two choices.

The sane one is to admit the mistake and use a different name, for example the next patch number. The manual points out that if the same name is kept, you may end up with two people who both have "version X" while having different "X"s.

The other one is to force the tag again anyway. The manual says that git does not, and should not, change tags behind users' backs, so people who already fetched the old tag keep it unless they take action.

Why this matters for your supply chain

If a build pipeline fetches a tag once and caches it, a later move of that tag will not reach the cache. If a fresh machine fetches the tag after the move, it gets different code. Two environments then build "the same version" from different source. That is hard to debug and, in a hostile case, a way to slip changed code under a trusted name.

Mutable names are a recurring pattern in supply chain trouble. Related reading: pin GitHub Actions to a commit SHA after tag repointing.

What to do as a consumer

  1. Record the commit hash next to the version in your lockfile, build notes or deployment record.
  2. Pin dependencies fetched from git by commit where the tool allows it.
  3. Compare what the tag points to now against your record.
git rev-parse v2.4.0^{commit}
git ls-remote --tags origin v2.4.0

If the remote hash differs from what you recorded, stop and ask why.

  1. Refetch tags deliberately only when you intend to take a changed tag.

What to do as a maintainer

  • Never move a published release tag. Ship a new version.
  • Protect release tags so only a few people can change them.
  • Say in the release notes if a release was withdrawn and which version replaces it.

Tag behaviour at a glance

SituationResult
Tag moved before anyone fetched itFine, nobody saw the old one
Tag moved after publishingFetched copies keep the old target
New name used insteadEveryone converges on the new version

A small example

Two developers pull tag v2.4.0 on Monday. On Tuesday the maintainer force pushes the tag to a different commit. The developer who pulls on Wednesday gets the new target, while the one who pulled on Monday still has the old one. Both run builds called v2.4.0 and the results differ. Neither did anything wrong, which is the point: the name stopped identifying a single thing.

Quick check

Can I trust a tag name as an identifier?

Only as a convenience. A commit hash identifies content. A tag is a movable label unless the host enforces immutability.

How do I notice a moved tag?

Compare the hash the remote reports with the hash you recorded when you first built. A difference means the tag now points somewhere else.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.