更新:
自从我最初回答这个问题以来,事情已经发生了变化。的Microsoft.NET.Sdk(这意味着你必须使用一个SDK风格的项目),现在包括用于添加支持提交哈希两个组件的版本信息以及到NuGet包的元数据,如果某些条件得到满足:
<SourceRevisionId>必须定义该属性。这可以通过添加如下目标来完成:
<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>
该目标执行将设置SourceRevisionId为缩写(8个字符)哈希的命令。BeforeTargets使它在创建程序集信息版本之前运行。
要将哈希包括在nuget包元数据中,<RepositoryUrl>还必须定义。
<SourceControlInformationFeatureSupported>属性必须为true,这将导致nuget pack任务也选择SourceRevisionId。
由于这种新技术更干净,最一致,因此我将使人们远离使用MSBuildGitHash软件包。
原版的:
我创建了一个简单的nuget程序包,您可以将其包含在项目中,它将为您解决此问题:https ://www.nuget.org/packages/MSBuildGitHash/
此nuget软件包实现了“纯” MSBuild解决方案。如果您不想依赖nuget包,则可以将这些Targets复制到csproj文件中,并且应将git hash作为自定义程序集属性包括在内:
<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>
这里有两个目标。第一个“ GetGitHash”将git哈希加载到名为BuildHash的MSBuild属性中,仅当尚未定义BuildHash 时才这样做。如果愿意,可以使用它在命令行上将其传递给MSBuild。您可以像这样将其传递给MSBuild:
MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL
第二个目标“ WriteGitHash”将哈希值写入名为“ CustomAssemblyInfo.cs”的临时“ obj”文件夹中的文件。该文件将包含如下一行:
[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]
此CustomAssemblyInfo.cs文件将被编译到您的程序集中,因此您可以使用反射AssemblyMetadata在运行时查找。以下代码显示了将AssemblyInfo类包含在同一程序集中时如何完成此操作。
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;
}
}
这种设计的一些好处是,它不会触摸项目文件夹中的任何文件,所有突变的文件都在“ obj”文件夹下。您的项目还将从Visual Studio或命令行中完全相同地构建。也可以轻松地为您的项目自定义它,并将与csproj文件一起进行源代码控制。