首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在.Net dll中嵌入git提交哈希

在.Net dll中嵌入git提交哈希
EN

Stack Overflow用户
提问于 2013-03-01 01:00:53
回答 17查看 50.6K关注 0票数 117

我正在构建一个C#应用程序,使用Git作为版本控制。

当我构建我的应用程序时,有没有办法自动将最后一个提交散列嵌入到可执行文件中?

例如,将提交散列打印到控制台将如下所示:

代码语言:javascript
复制
class PrintCommitHash
{
    private String lastCommitHash = ?? // What do I put here?
    static void Main(string[] args)
    {
        // Display the version number:
        System.Console.WriteLine(lastCommitHash );
    }
}

请注意,这必须在build时完成,而不是在运行时,因为我部署的可执行文件将无法访问git存储库。

关于C++的一个相关问题可以在here上找到。

编辑

根据@mattanja的请求,我发布了我在项目中使用的git钩子脚本。设置:

钩子是linux shell脚本,放在: path_to_project.git\hooks

  • If下。如果您正在使用msysgit,则
  • 文件夹中已经包含了一些示例脚本。为了让git调用它们,从脚本名称中删除'.sample‘扩展名。
  • 钩子脚本的名称与调用它们的事件相匹配。在我的示例中,我修改了提交后,post-merge.
  • My AssemblyInfo.cs文件直接位于项目路径下(与.git文件夹处于同一级别)。它包含23行代码,我使用git生成第24行代码。

由于我的linux外壳有点生疏,该脚本简单地将AssemblyInfo.cs的前23行读取到一个临时文件,将git散列回显到最后一行,然后将该文件重命名为AssemblyInfo.cs。我相信有更好的方法可以做到这一点:

代码语言:javascript
复制
#!/bin/sh
cmt=$(git rev-list --max-count=1 HEAD)
head -23 AssemblyInfo.cs > AssemblyInfo.cs.tmp
echo [assembly: AssemblyFileVersion\(\"$cmt\"\)] >> AssemblyInfo.cs.tmp
mv AssemblyInfo.cs.tmp AssemblyInfo.cs

希望这能有所帮助。

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2013-03-01 03:14:54

我们在git中使用标签来跟踪版本。

代码语言:javascript
复制
git tag -a v13.3.1 -m "version 13.3.1"

您可以通过以下方式从git获取带有散列的版本:

代码语言:javascript
复制
git describe --long

我们的构建过程将git散列放在AssemblyInfo.cs文件的AssemblyInformationalVersion属性中:

代码语言:javascript
复制
[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]

编译完成后,您可以从windows资源管理器中查看版本:

您也可以通过以下方式以编程方式获取它:

代码语言:javascript
复制
var build = ((AssemblyInformationalVersionAttribute)Assembly
  .GetAssembly(typeof(YOURTYPE))
  .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
  .InformationalVersion;

其中,您的类型是程序集中具有AssemblyInformationalVersion属性的任何类型。

票数 66
EN

Stack Overflow用户

发布于 2013-03-01 04:33:28

您可以将version.txt文件嵌入到可执行文件中,然后从可执行文件中读取version.txt。要创建version.txt文件,请使用git describe --long

以下是步骤:

使用Build事件调用git

  • 右键单击项目,然后在Build Events中选择Properties
  • ,add Pre-Build event包含(请注意引号):

"C:\Program Files\Git\bin\git.exe“describe --long > "$(ProjectDir)\version.txt”

这将在项目目录中创建一个version.txt文件。

在可执行文件中嵌入version.txt

  • 右键单击项目并选择Add Existing Item
  • Add version.txt file (更改文件选择器筛选器使您可以看到所有文件)。to e224添加文件后,在解决方案资源管理器中右键单击它并选择Properties
  • Change

Build

  • to Embedded Resource
  • Change Copy to Output
  • to Copy Always<>H229
  • 将版本.txt添加到.gitignore文件

读取嵌入的文本文件版本字符串

下面是读取嵌入式文本文件版本字符串的一些示例代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace TryGitDescribe
{
    class Program
    {
        static void Main(string[] args)
        {
            string gitVersion= String.Empty;
            using (Stream stream = Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("TryGitDescribe." + "version.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                gitVersion= reader.ReadToEnd();
            }

            Console.WriteLine("Version: {0}", gitVersion);
            Console.WriteLine("Hit any key to continue");
            Console.ReadKey();
        }
    }
}
票数 83
EN

Stack Overflow用户

发布于 2017-07-22 07:23:55

更新:

自从我最初回答这个问题以来,事情发生了变化。Microsoft.NET.Sdk (意味着您必须使用sdk样式的项目)现在支持将提交散列添加到程序集信息版本以及nuget包元数据,前提是满足以下条件:

  1. 必须定义<SourceRevisionId>属性。这可以通过像这样添加一个目标来完成:

代码语言:javascript
复制
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
    <Exec 
      Command="git describe --long --always --dirty --exclude=* --abbrev=8"
      ConsoleToMSBuild="True"
      IgnoreExitCode="False"
      >
      <Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/>
    </Exec>
  </Target>

此目标执行一个命令,该命令将SourceRevisionId设置为缩写(8个字符)散列。BeforeTargets使其在创建程序集信息版本之前运行。

  1. 若要将散列包括在nuget包元数据中,还必须定义<RepositoryUrl>

  1. <SourceControlInformationFeatureSupported>属性必须为true,这会导致nuget pack任务也拾取SourceRevisionId。

我会引导人们远离使用MSBuildGitHash包,因为这种新技术更干净、最一致。

原件:

我已经创建了一个简单的nuget包,您可以将它包含在您的项目中,它将为您解决这个问题:https://www.nuget.org/packages/MSBuildGitHash/

这个nuget包实现了一个“纯”MSBuild解决方案。如果你不想依赖nuget包,你可以简单地将这些目标复制到你的csproj文件中,并且它应该包含git散列作为自定义程序集属性:

代码语言:javascript
复制
<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 &gt; $(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类时执行此操作。

代码语言:javascript
复制
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文件一起进行源代码控制。

票数 74
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15141338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档