Squash Merge Causes Orphaned Git Tags — Why git describe Stops Finding Them and How to Fix It

Squash Merge Causes Orphaned Git Tags — Why git describe Stops Finding Them and How to Fix It

When you squash merge a feature branch, all commits from that branch are combined into a single new commit on main. This new commit has no ancestry relationship with the original commits on the feature branch. As a result, any git tags that were placed on commits within the feature branch become orphaned from the perspective of main's commit history. Since git describe works by walking backwards through the ancestry chain from the current commit to find the nearest reachable tag, it cannot see those feature branch tags at all. They are simply not reachable from main. The root cause is that squash merge intentionally discards the original commit graph. The new squash commit on main is a completely fresh commit whose parent is the previous tip of main, not any commit from the feature branch. The feature branch commits, along with any tags pointing to them, become dangling references that are not part of the main branch history. This causes several practical problems. Running git describe on main will skip over those tags entirely and either find an older tag further back in history or report that no tag is found. Automated versioning systems that rely on git describe will produce incorrect or unexpected version strings. If you later prune unreachable objects, the orphaned tags may cause confusion or need to be cleaned up manually. The correct approach is to place your tags on main after the squash merge is complete. Once the squash commit has landed on main, you tag that specific commit. This ensures the tag is reachable from the tip of main and from any future commits on main, making git describe work correctly. If you need to tag a specific version or release, do so on the resulting squash commit rather than on any commit during feature development. If you want to preserve some reference to where things stood on the feature branch, you can keep the feature branch itself or create a separate ref, but the authoritative tag for release or versioning purposes should always live on the main line of history after the merge. This keeps your ancestry chain intact and ensures all tools that depend on reachable tag traversal behave as expected.
2026.07.10

This page has been translated by machine translation. View original

When using GitHub's squash merge, git describe --tags --abbrev=0 stopped finding the latest tag. The cause is that tags created on a feature branch become orphaned by squash merge. Here I'll summarize the reproduction steps, diagnostic methods, and solutions.

Prerequisites / Environment

  • Git 2.49
  • GitHub (using PR squash merge)
  • Release automation script using git describe --tags for version detection

What Happened

I was using the following command to retrieve versions in a release automation script.

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

Even though I had released v0.6.3, this command returned v0.6.0. The tags v0.6.1, v0.6.2, and v0.6.3 were not being found.

Cause: Tag Orphaning by Squash Merge

The Release Flow Problem

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

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

What Squash Merge Does

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

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

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

How git describe Works

git describe --tags --abbrev=0 returns the first tag found by traversing the ancestors of the current commit. When run on main, it only traverses ancestors X → Y → Z → S, so the tag attached to commit C is not 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 tag "orphaning." The tags themselves exist, but they are unreachable from the commit history of main.

Diagnostic Methods

Check Whether a Tag Is Orphaned

# Check if the commit pointed to by the tag 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 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 pointed to by the tag
git rev-parse v0.6.3

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

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

Solution: Create Tags on Main After Squash Merge

Updated 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. Checkout 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 ensures the tag always points to a commit in the history of main.

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

Fixing Existing Orphaned Tags

Orphaned tags can be reassigned to the correct commit on main using git tag -f.

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

# Squash merge commit messages include PR numbers, so use those to identify them
git log --oneline main | head -20

Once the corresponding commit is found, reassign the tag.

# Reassign 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 remote
git push origin --tags --force

Verification after fixing:

$ 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

This Does Not Happen with Regular Merge

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

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

Since C can be reached from merge commit M, tags are found by git describe.

Rebase merge has the same problem. Since rebase cherry-picks commits, new SHAs are generated.

Merge Method Tags Become Orphaned?
Regular merge No
Squash merge Yes
Rebase merge Yes

Summary

  • Squash merge creates a new commit on main with a different SHA than the feature branch commits
  • Tags created on the feature branch become unreachable from main's ancestors and cannot be detected by git describe
  • Solution: Create tags on main after squash merge
  • Tag orphaning can be diagnosed with git merge-base --is-ancestor
  • Orphaned tags can be reassigned to commits on main using git tag -f

When using git describe --tags in release automation, be careful when combining it with squash merge.

References

Share this article