Have you ever shipped a deploy, only to get a bug report minutes later with no way to tell which commit is actually running in production — leaving you bouncing between logs and CI history to figure it out? By default, /actuator/info is empty, but combining the build-info plugin with the git-commit-id-plugin lets you automatically embed the version and commit hash at build time.

This article covers everything from management.info.* configuration, to generating build-info and git.properties with Maven/Gradle, to verification scripts for CI/CD — all assuming Spring Boot 3.x. It’s aimed at readers who’ve already enabled health/info following the Actuator getting-started article; it does not cover customizing InfoContributor in general or health checks.

Why /actuator/info comes back empty

Actuator’s info endpoint works by having BuildInfoContributor and GitInfoContributor look for META-INF/build-info.properties and git.properties on the classpath and assemble the values from them. The real reason info comes back empty is almost always that these two files were never generated.

management.info.build.enabled and management.info.git.enabled default to true in Spring Boot 3.x. Things work even if you omit them, but spelling them out explicitly as shown below makes it clear from the config file alone that they’re enabled — a good practice when running this as a team.

management:
  info:
    build:
      enabled: true
    git:
      enabled: true
      mode: simple
management.info.build.enabled=true
management.info.git.enabled=true
management.info.git.mode=simple

mode: simple (the default) returns the branch name and short commit hash as strings. With mode: full, git.commit.id becomes an object like {full: ..., abbrev: ...}, and detailed information such as the committer and commit timestamp is included as well. Since the verification script described later reads git.commit.id as a string with jq, this article uses simple.

Generating build-info and git.properties with Maven

Configure the build-info goal on spring-boot-maven-plugin, and the revision goal on git-commit-id-maven-plugin.

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals><goal>build-info</goal></goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>io.github.git-commit-id</groupId>
      <artifactId>git-commit-id-maven-plugin</artifactId>
      <version>9.0.1</version>
      <executions>
        <execution>
          <goals><goal>revision</goal></goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

If you inherit from spring-boot-starter-parent, you can omit the <version> for spring-boot-maven-plugin, since the pluginManagement value is used automatically. git-commit-id-maven-plugin, on the other hand, isn’t included in Spring’s official pluginManagement, so omitting <version> will cause mvn package to fail with a plugin resolution error at build time. Always specify the version explicitly as shown above, and check Maven Central for the latest release.

Running mvn package writes out target/classes/META-INF/build-info.properties and target/classes/git.properties, which Spring Boot automatically loads at startup. If you want to change the output location, you can specify the git.properties path with generateGitPropertiesFilename, but unless you have a specific reason, the default location works fine.

Generating build-info and git.properties with Gradle

In Gradle, springBoot.buildInfo() generates the build information. For git information, note that git-commit-id-plugin was originally built for Maven, and its Gradle counterpart is a separate third-party plugin. In the Gradle ecosystem, gradle-git-properties is widely used for the same purpose, so this article uses it as well.

plugins {
    id("com.gorylenko.gradle-git-properties") version "4.0.1"
}

springBoot {
    buildInfo()
}

With Maven, you had to explicitly specify the goal via <executions>, but with Gradle, simply applying the plugin automatically hooks the generateGitProperties task into build/bootJar, generating git.properties with no extra configuration. The bootBuildInfo task likewise depends on build/bootJar, so you don’t need to run it separately.

Gradle has no equivalent to Maven’s pluginManagement, so specifying a version is mandatory. Check the Gradle Plugin Portal for the latest release.

Checking the /actuator/info output

Start the app and hit it with curl.

curl -s localhost:8080/actuator/info | jq
{
  "build": {
    "artifact": "myapp",
    "version": "1.4.0",
    "time": "2026-10-01T03:12:45Z"
  },
  "git": {
    "branch": "main",
    "commit": {
      "id": "3f2a9c1",
      "time": "2026-09-30T21:05:00Z"
    }
  }
}

The local values here are just for a sanity check. What you actually care about in production is the value built via CI/CD, so do the final verification on the pipeline.

Verifying the deployed version in CI/CD

Once the configuration is in place, add a verification step to your pipeline that hits /actuator/info right after deployment and compares it against the expected commit. By comparing the commit hash CI already has (e.g. GITHUB_SHA) against the git.commit.id returned from production, and failing the deploy on a mismatch, you can catch a stale version lingering in production early.

That said, right after setting up this check, you may run into cases where the value doesn’t reflect what you expect. Common culprits include: GitHub Actions’ default shallow clone (fetch-depth: 1), which leaves insufficient git history and results in an incomplete git.properties; Docker multi-stage builds where an old cached layer leaves build-info/git.properties stale while the rest of the image updates; and environment-specific config files like application-prod.yml overriding management.info.*, causing info to come back empty only in production. Before writing the verification script, it’s reassuring to hit /actuator/info directly in a production-equivalent environment and confirm its contents once.

Example verification script implementation

#!/bin/bash
set -euo pipefail

EXPECTED_COMMIT="${GITHUB_SHA:0:7}"

RESPONSE=$(curl -sf https://example.com/actuator/info) || {
  echo "failed to reach /actuator/info"
  exit 1
}

ACTUAL_COMMIT=$(echo "$RESPONSE" | jq -r '.git.commit.id // empty')

if [ -z "$ACTUAL_COMMIT" ]; then
  echo "git.commit.id not found in response: $RESPONSE"
  exit 1
fi

if [ "$ACTUAL_COMMIT" != "$EXPECTED_COMMIT" ]; then
  echo "commit mismatch: expected=$EXPECTED_COMMIT actual=$ACTUAL_COMMIT"
  exit 1
fi

echo "deployed commit verified: $ACTUAL_COMMIT"

curl -f catches communication errors, and jq catches missing values, failing the script on either. Inserting this at the end of your deploy job lets you catch a stale container lingering around much sooner.

Summary

Simply combining the build-info plugin with git-commit-id-plugin turns /actuator/info into a practical endpoint that answers “what version and commit is running right now.” Verifying this value right after a CI/CD deploy can significantly shorten the time it takes to decide whether a rollback is needed.

If you want to extend Actuator further to include health checks, see the custom HealthIndicator article; if you want to revisit the basics of containerization, check out the Docker containerization article as well.