Git Tags Become Orphaned with Squash Merge — Causes of git describe Failing to Detect Them and How to Fix It

Git Tags Become Orphaned with Squash Merge — Causes of git describe Failing to Detect Them and How to Fix It

Why git tags created on a feature branch become orphaned after a squash merge and can't be found by git describe, and how to fix it: tag on main after the squash merge.
2026.07.10

This page has been translated by machine translation. View original

After I started using GitHub's squash merge, git describe --tags --abbrev=0 could no longer find the latest tag. The cause is that tags created on a feature branch become orphaned by the squash merge. This article summarizes the reproduction steps, how to diagnose it, and how to fix it.

Prerequisites and Environment

  • Git 2.49
  • GitHub (using squash merge for PRs)
  • Version detection via git describe --tags in a release automation script

What Happened

To get the version in the release automation script, I was using the following command.

CURRENT=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")

I was sure I had released v0.6.3, but this command returned v0.6.0. The tags v0.6.1, v0.6.2, and v0.6.3 could not be found.

Cause: Tags Orphaned by Squash Merge

Problem with the Release Flow

The release flow at the time was in the following order.

  1. Implement on a feature branch
  2. Version bump commit
  3. Create the tag on the feature branch (git tag v0.6.3)
  4. Push the branch and tag
  5. Create a PR → squash merge

What Squash Merge Does

Squash merge creates a new commit on main that combines all the commits of the feature branch into one.

squash-merge-orphans-git-tags-squash-orphan

The important point is that the squash merge commit S has a different SHA from C. The tag v0.6.3 points to commit C, but C does not exist among the ancestors of main.

How git describe Works

git describe --tags --abbrev=0 walks back through the ancestors of the current commit and returns the first tag it finds. When run on main, it only traverses the ancestors X → Y → Z → S, so the tag attached to commit C is never found.

# Run on main
$ git describe --tags --abbrev=0
v0.6.0  # v0.6.1, v0.6.2, v0.6.3 are not found

This is what it means for a tag to be "orphaned". The tag itself exists, but it cannot be reached from main's commit history.

How to Diagnose

Check Whether a Tag Is Orphaned

# Check whether the commit the tag points to is an ancestor of main
git merge-base --is-ancestor $(git rev-parse v0.6.3) main
echo $?  # 0 = is an ancestor, 1 = orphaned

List the Orphan Status of All Tags

for tag in $(git tag --sort=-v:refname); do
  if git merge-base --is-ancestor "$(git rev-parse "$tag")" main 2>/dev/null; then
    echo "OK   $tag"
  else
    echo "ORPHAN $tag"
  fi
done

Output:

ORPHAN v0.6.3
ORPHAN v0.6.2
ORPHAN v0.6.1
OK   v0.6.0
OK   v0.5.0

Check the Relationship Between Tags and Commits

# SHA of the commit the tag points to
git rev-parse v0.6.3

# SHA of main's latest commit (the squash merge commit)
git rev-parse main

# Different SHAs are shown → the tag is not on main

Fix: Create Tags on main After the Squash Merge

Corrected Flow

  1. Implement on a feature branch
  2. Version bump commit (do not create the tag yet)
  3. Push the branch and create a PR
  4. Squash merge
  5. Check out main and pull
  6. Create the tag on the squash merge commit
  7. Push the tag
# After squash merging the PR
git checkout main
git pull origin main

# Create the tag on the squash merge commit
git tag v0.6.3
git push origin --tags

This way, the tag reliably points to a commit in main's history.

squash-merge-orphans-git-tags-fixed-flow

Repairing Existing Orphaned Tags

Tags that have already been orphaned can be moved to the correct commits on main with git tag -f.

First, identify the squash merge commit corresponding to each tag.

# The squash merge commit message contains the PR number, so use it to identify the commit
git log --oneline main | head -20

Once you find the corresponding commits, move the tags.

# Move the tags locally
git tag -f v0.6.3 <squash-merge-commit-sha>
git tag -f v0.6.2 <squash-merge-commit-sha>
git tag -f v0.6.1 <squash-merge-commit-sha>

# Force push to the remote
git push origin --tags --force

Verification after the repair:

$ git describe --tags --abbrev=0
v0.6.3  # Correctly detected

$ for tag in v0.6.{1,2,3}; do
    git merge-base --is-ancestor "$(git rev-parse "$tag")" main && echo "OK $tag" || echo "ORPHAN $tag"
  done
OK v0.6.1
OK v0.6.2
OK v0.6.3

It Doesn't Happen with a Regular Merge

With a regular merge (non-squash), the feature branch's commits are included in main's ancestors, so this problem does not occur.

squash-merge-orphans-git-tags-normal-merge

Since you can walk from the merge commit M to C, git describe can find the tag.

The same problem occurs with rebase merge. Rebase cherry-picks commits, so new SHAs are generated.

Merge method Are tags orphaned?
Regular merge No
Squash merge Yes
Rebase merge Yes

Summary

  • Squash merge creates a new commit on main with a different SHA from the feature branch's commits
  • Tags created on the feature branch cannot be reached from main's ancestors, so git describe can no longer detect them
  • Fix: create tags on main after the squash merge
  • You can diagnose orphaned tags with git merge-base --is-ancestor
  • Already-orphaned tags can be moved to commits on main with git tag -f

If you use git describe --tags in release automation, you need to be careful about combining it with squash merge.

References

Share this article