Skip to content

Instantly share code, notes, and snippets.

@Trogious
Last active March 29, 2026 09:26
Show Gist options
  • Select an option

  • Save Trogious/fbf69afee2ff049951ac6930de7bd0da to your computer and use it in GitHub Desktop.

Select an option

Save Trogious/fbf69afee2ff049951ac6930de7bd0da to your computer and use it in GitHub Desktop.
How to get latest git tag or commit ID (gradle)

How to get latest git tag or commit ID (gradle)

The following will give you the latest git tag name (if the HEAD is tagged) or latest commit ID otherwise. The getAppVersion function returns the end value.

Why is this useful?

I use it to name packages of my builds and other versioning purposes in my Android projects.

The code:

def getAppVersion = { ->
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'rev-parse', '--short', 'HEAD'
        standardOutput = stdout
    }
    def commitId = stdout.toString().replace("\n", "").replace("\r", "").trim()
    stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'tag', '--points-at', commitId
        standardOutput = stdout
    }
    def tagName = stdout.toString().replace("\n", "").replace("\r", "").trim()
    def versionName = 'git-' + commitId
    if (tagName != null && "" != tagName) {
        versionName = tagName
    }
    return versionName
}
@4shutosh
Copy link
Copy Markdown

4shutosh commented Aug 6, 2024

A KTS version

fun getGitTag(): String {
  val stdout = ByteArrayOutputStream()
  val stdout2 = ByteArrayOutputStream()
  exec {
    workingDir("change directory to root")
    commandLine("git", "rev-parse", "--short", "HEAD")
    standardOutput = stdout
  }
  val commitId = stdout.toString().replace("\n", "").replace("\r", "").trim()
  exec {
    workingDir("change directory to root")
    commandLine("git", "tag", "--points-at", commitId)
    standardOutput = stdout2
  }
  val tagName = stdout2.toString().replace("\n", "").replace("\r", "").trim()
  var versionName = commitId
  if (tagName.isNotEmpty()) {
    versionName = tagName
  }
  return versionName
}

@barendgehrels
Copy link
Copy Markdown

barendgehrels commented Mar 29, 2026

A modern .kts version :

// gitTagProvider defines how to get the git tag (compatible with configuration cache)
val gitTagProvider = providers.exec { 
     commandLine("git", "describe", "--tags", "--always")
 }.standardOutput.asText

// Gets the git tag, including "ahead of" information.
// Possibly including commit distance and hash suffix
// It might be: `1.0.42` or `1.0.42-1-g1caf41`
fun getGitTag(): String = gitTagProvider.get().trim() 

// Returns a cleaned git-tag, that would then be
// `1.0.42` even if the tag is `1.0.42-1-g1caf41`)
fun getSemanticVersion(): String {
    val tag = getGitTag()
    val parts = tag.split(".", "-")
    val major = parts.getOrNull(0)?.toIntOrNull() ?: 0
    val minor = parts.getOrNull(1)?.toIntOrNull() ?: 0
    val patch = parts.getOrNull(2)?.toIntOrNull() ?: 0
    val result = "${major}.${minor}.${patch}"
    return result
}

Claude comments:

It's about Gradle configuration cache compatibility.

If you called git describe directly (e.g. via Runtime.getRuntime().exec(...) or a bare ProcessBuilder), it would execute
during the configuration phase — every time Gradle configures the project. That breaks Gradle's configuration cache because:

  1. The configuration cache serializes the entire configured build. External process calls during configuration are not
    cacheable — Gradle can't know if the output would change.
  2. Gradle would have to invalidate the configuration cache on every build, defeating its purpose.

By wrapping it in providers.exec { ... }, you get a lazy Provider. The command is:

  • Not executed during configuration — it's just declared
  • Only executed when .get() is called during task execution (or when Gradle needs the value)
  • Compatible with the configuration cache — Gradle knows it's an external process provider and can track it properly

So gitTagProvider is a lazy handle. The actual git describe call is deferred until something calls getGitTag() →
gitTagProvider.get(). This is the Gradle-idiomatic way to shell out since the providers.exec API was added (Gradle 7.5+).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment