ATUALIZAR:
As coisas evoluíram desde que originalmente respondi a esta pergunta. O Microsoft.NET.Sdk(o que significa que você deve usar um projeto no estilo sdk) agora inclui suporte para adicionar o hash de confirmação tanto à versão informativa do assembly quanto aos metadados do pacote nuget, se algumas condições forem atendidas:
- A
<SourceRevisionId>propriedade deve ser definida. Isso pode ser feito adicionando um alvo como este:
<Target Name="InitializeSourceControlInformation" BeforeTargets="AddSourceRevisionToInformationalVersion">
<Exec
Command="git describe --long --always --dirty --exclude=* --abbrev=8"
ConsoleToMSBuild="True"
IgnoreExitCode="False"
>
<Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/>
</Exec>
</Target>
Este destino executa um comando que será definido SourceRevisionIdcomo o hash abreviado (8 caracteres). O BeforeTargets faz com que isso seja executado antes que a versão informativa do assembly seja criada.
Para incluir o hash nos metadados do pacote nuget, o <RepositoryUrl>também deve ser definido.
<SourceControlInformationFeatureSupported>deve ser true, isso faz com que a tarefa do pacote nuget pegue o SourceRevisionId também.
Eu evitaria que as pessoas usassem o pacote MSBuildGitHash, já que essa nova técnica é mais limpa e consistente.
ORIGINAL:
Eu criei um pacote nuget simples que você pode incluir em seu projeto que cuidará disso para você: https://www.nuget.org/packages/MSBuildGitHash/
Este pacote nuget implementa uma solução MSBuild "pura". Se você preferir não depender de um pacote nuget, pode simplesmente copiar esses alvos em seu arquivo csproj e ele deve incluir o hash git como um atributo de assembly personalizado:
<Target Name="GetGitHash" BeforeTargets="WriteGitHash" Condition="'$(BuildHash)' == ''">
<PropertyGroup>
<!-- temp file for the git version (lives in "obj" folder)-->
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
</PropertyGroup>
<!-- write the hash to the temp file.-->
<Exec Command="git -C $(ProjectDir) describe --long --always --dirty > $(VerFile)" />
<!-- read the version into the GitVersion itemGroup-->
<ReadLinesFromFile File="$(VerFile)">
<Output TaskParameter="Lines" ItemName="GitVersion" />
</ReadLinesFromFile>
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
<PropertyGroup>
<BuildHash>@(GitVersion)</BuildHash>
</PropertyGroup>
</Target>
<Target Name="WriteGitHash" BeforeTargets="CoreCompile">
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
<PropertyGroup>
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
</PropertyGroup>
<!-- includes the CustomAssemblyInfo for compilation into your project -->
<ItemGroup>
<Compile Include="$(CustomAssemblyInfoFile)" />
</ItemGroup>
<!-- defines the AssemblyMetadata attribute that will be written -->
<ItemGroup>
<AssemblyAttributes Include="AssemblyMetadata">
<_Parameter1>GitHash</_Parameter1>
<_Parameter2>$(BuildHash)</_Parameter2>
</AssemblyAttributes>
</ItemGroup>
<!-- writes the attribute to the customAssemblyInfo file -->
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
</Target>
Existem dois alvos aqui. O primeiro, "GetGitHash", carrega o hash git em uma propriedade MSBuild chamada BuildHash, ele só faz isso se BuildHash ainda não estiver definido. Isso permite que você passe para o MSBuild na linha de comando, se preferir. Você poderia passá-lo para o MSBuild assim:
MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL
O segundo destino, "WriteGitHash", gravará o valor hash em um arquivo na pasta temporária "obj" chamada "CustomAssemblyInfo.cs". Este arquivo conterá uma linha semelhante a:
[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]
Este arquivo CustomAssemblyInfo.cs será compilado em seu assembly, para que você possa usar a reflexão para procurar o AssemblyMetadatatempo de execução. O código a seguir mostra como isso pode ser feito quando a AssemblyInfoclasse está incluída no mesmo assembly.
using System.Linq;
using System.Reflection;
public static class AssemblyInfo
{
/// <summary> Gets the git hash value from the assembly
/// or null if it cannot be found. </summary>
public static string GetGitHash()
{
var asm = typeof(AssemblyInfo).Assembly;
var attrs = asm.GetCustomAttributes<AssemblyMetadataAttribute>();
return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
}
}
Alguns benefícios deste design é que ele não toca em nenhum arquivo na pasta do projeto, todos os arquivos modificados estão na pasta "obj". Seu projeto também será construído de forma idêntica no Visual Studio ou na linha de comando. Ele também pode ser facilmente personalizado para o seu projeto e terá o código-fonte controlado junto com o arquivo csproj.