# Fix Git Shallow Clone Missing Tags Causing Build Failures

You clone a repository with --depth 1 for faster CI builds:

bash
git clone --depth 1 https://github.com/user/repo.git

But your build script fails because it cannot find git tags:

bash
git describe --tags
# fatal: No tags can describe 'abc1234'

Or:

bash
git tag -l "v*"
# (empty - no tags found)

Shallow clones do not include tags by default, which breaks version detection, semantic release, and build scripts that rely on tag information.

Understanding Shallow Clone Limitations

A shallow clone (--depth 1) only downloads the most recent commit. It does not include: - Full commit history - Tags (unless explicitly fetched) - Branches other than the one you cloned

This makes it fast but incomplete. Many build tools assume a full clone.

Step 1: Fetch Tags After Cloning

If you already have a shallow clone, fetch the tags:

bash
git fetch --depth=1 origin "+refs/tags/*:refs/tags/*"

Or fetch all tags:

bash
git fetch --tags

The --tags flag fetches all tags from the remote, even if they are not on the cloned branch.

Step 2: Clone With Tags

For a fresh clone that includes tags:

bash
git clone --depth 1 --no-single-branch https://github.com/user/repo.git

The --no-single-branch flag fetches all branch references, which includes tags pointing to those branches. However, tags pointing to commits not on any fetched branch will still be missing.

Step 3: The Correct Approach for CI

For CI builds that need both speed and tag information:

bash
# Shallow clone with tag fetching
git clone --depth 50 https://github.com/user/repo.git
cd repo
git fetch --tags

Using --depth 50 instead of --depth 1 provides enough history for git describe to work for recent tags. The git fetch --tags ensures all tags are available.

Step 4: GitHub Actions Specific Fix

In GitHub Actions, the default actions/checkout performs a shallow clone:

yaml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Full clone (slow but complete)

Or for a shallow clone with tags:

yaml
- uses: actions/checkout@v4
  with:
    fetch-depth: 50
    fetch-tags: true

The fetch-tags: true option (available in v4+) fetches tags even with shallow clones.

Step 5: GitLab CI Specific Fix

In GitLab CI, the default behavior depends on the GIT_STRATEGY variable:

```yaml variables: GIT_STRATEGY: clone GIT_DEPTH: 50

script: - git fetch --tags - git describe --tags ```

Set GIT_DEPTH to control shallow clone depth and explicitly fetch tags.

Step 6: Semantic Release and git-describe

Tools like semantic-release and git describe need tag history to determine the current version:

bash
git describe --tags --always --dirty
# v2.3.1-15-gabc1234

This shows: tag v2.3.1, 15 commits after the tag, at commit abc1234.

For this to work, the commit being described must be reachable from a tag in the clone. With --depth 1, if the current commit IS the tagged commit, it works. If the current commit is 20 commits after the latest tag, you need at least --depth 20.

Step 7: Determining the Right Depth

Calculate the minimum depth needed:

bash
# On a full clone, find the distance to the nearest tag
git describe --tags --long
# v2.3.1-15-gabc1234
# Need at least depth 15

Set your shallow clone depth to this number plus a buffer:

bash
git clone --depth 30 https://github.com/user/repo.git

Step 8: Unshallow an Existing Clone

If you have a shallow clone and need full history:

bash
git fetch --unshallow

This converts the shallow clone to a full clone by downloading all missing history. This can take significant time and bandwidth for large repositories.

For partial unshallowing (only up to a specific tag):

bash
git fetch --depth=100

This extends the history to 100 commits, which may be enough for your build needs without downloading the entire history.