wctb.net/blog

Pulling Git info into C# assemblies using pure MSBuild

If you want your .NET apps to know from which commit they were built, you’re in luck, because MSBuild lets you automate this pretty easily.

Here is a complete incantation that you can just stick into your .csproj file:

<Target Name="GetGitInfo" BeforeTargets="GetAssemblyAttributes">
  <Exec Command="git rev-parse HEAD" UseCommandProcessor="false" ConsoleToMSBuild="true" IgnoreExitCode="false">
    <Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHash" />
  </Exec>
  <!-- On Windows you have to double the % here: -->
  <Exec Command="git show -s --format=%%ci" UseCommandProcessor="false" ConsoleToMSBuild="true" IgnoreExitCode="false">
    <Output TaskParameter="ConsoleOutput" PropertyName="GitCommitTime" />
  </Exec>
  <!-- Replace “origin” with the name of your remote if it differs: -->
  <Exec Command="git remote get-url origin" UseCommandProcessor="false" ConsoleToMSBuild="true" IgnoreExitCode="false">
    <Output TaskParameter="ConsoleOutput" PropertyName="GitRemoteUrl" />
  </Exec>

  <PropertyGroup>
    <GitCommitHash>$([System.String]::Copy('$(GitCommitHash)').Trim())</GitCommitHash>
    <GitCommitTime>$([System.String]::Copy('$(GitCommitTime)').Trim())</GitCommitTime>
    <GitRemoteUrl>$([System.String]::Copy('$(GitRemoteUrl)').Trim())</GitRemoteUrl>
  </PropertyGroup>

  <ItemGroup>
    <AssemblyMetadata Include="GitCommitHash" Value="$(GitCommitHash)" />
    <AssemblyMetadata Include="GitCommitTime" Value="$(GitCommitTime)" />
    <AssemblyMetadata Include="GitRemoteUrl" Value="$(GitRemoteUrl)" />
  </ItemGroup>
</Target>

Every time the project is built, this will add assembly metadata attributes to your MyProject.AssemblyInfo.cs, eg.:

[assembly: System.Reflection.AssemblyMetadata("GitCommitHash", "15a88b68a9bc593a10cca540929e48ff639d0efa")]

To surface these in your application, you may add a static class or perhaps a singleton service:

static internal class BuildInfo
{
    public static readonly string CommitHash = "";
    public static readonly string CommitHashShort = "";
    public static readonly DateTime CommitTime;

    static BuildInfo()
    {
        var assemblyMetadata = typeof(Program).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>();

        CommitHash = assemblyMetadata?.FirstOrDefault(attr => attr.Key == "GitCommitHash")?.Value ?? "";
        CommitHashShort =  CommitHash[..Math.Min(7, CommitHash.Length)];

        DateTime.TryParse(assemblyMetadata?.FirstOrDefault(attr => attr.Key == "GitCommitTime")?.Value, out CommitTime);
    }
}