热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在。netdll中嵌入git提交散列-Embedgitcommithashina.Netdll

ImbuildingaC#application,usingGitasmyversioncontrol.我正在构建一个c#应用程序,使用Git作为我的版本控制。Isthe

I'm building a C# application, using Git as my version control.

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

Is there a way to automatically embed the last commit hash in the executable when I build my application?

是否有一种方法可以在构建应用程序时自动将最后的提交散列嵌入到可执行文件中?

For example, printing the commit hash to console would look something like:

例如,将提交散列打印到控制台将会是:

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

Note that this has to be done at build time, not runtime, as my deployed executable will not have the git repo accessible.

请注意,这必须在构建时完成,而不是在运行时完成,因为我部署的可执行文件不能访问git repo。

A related question for C++ can be found here.

EDIT

Per @mattanja's request, I'm posting the git hook script I use in my projects. The setup:

有关c++的一个相关问题可以在这里找到。根据@mattanja的请求进行编辑,我正在发布我在项目中使用的git hook脚本。设置:

  • The hooks are linux shell scripts, which are placed under: path_to_project\.git\hooks
  • 钩子是linux shell脚本,放在:path_to_project\.git\hook下面
  • If you are using msysgit, the hooks folder already contains some sample scripts. In order to make git call them, remove the '.sample' extension from the script name.
  • 如果您正在使用msysgit,那么hooks文件夹已经包含了一些示例脚本。为了让git调用它们,删除'。从脚本名称中选择“扩展名”。
  • The names of the hook scripts match the event that invokes them. In my case, I modified post-commit and post-merge.
  • 钩子脚本的名称与调用它们的事件相匹配。在我的例子中,我修改了后提交和后合并。
  • My AssemblyInfo.cs file is directly under the project path (same level as the .git folder). It contains 23 lines, and I use git to generate the 24th.
  • 我的AssemblyInfo。cs文件直接位于项目路径下(与.git文件夹相同级别)。它包含23行,我使用git生成第24行。

As my linux-shelling a bit rusty, the script simply reads the first 23-lines of AssemblyInfo.cs to a temporary file, echos the git hash to the last line, and renames the file back to AssemblyInfo.cs. I'm sure there are better ways of doing this:

当我的linux-shell有点生锈的时候,这个脚本只是读取了第一个23行的汇编信息。cs到一个临时文件,将git散列回最后一行,并将文件重命名为AssemblyInfo.cs。我相信有更好的方法:

#!/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

Hope this helps.

希望这个有帮助。

11 个解决方案

#1


41  

We use tags in git to track versions.

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

git tag -a v13.3.1 -m "version 13.3.1"

You can get the version with hash from git via:

您可以通过以下方式从git获取哈希版本:

git describe --long

Our build process puts the git hash in the AssemblyInformationalVersion attribute of the AssemblyInfo.cs file:

我们的构建过程将git散列放在程序集信息版本属性中。cs文件:

[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]

Once you compile, you can view the version from windows explorer:

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

enter image description here

You can also get it programmatically via:

你亦可透过下列途径以程式方式取得:

var build = ((AssemblyInformationalVersionAttribute)Assembly
  .GetAssembly(typeof(YOURTYPE))
  .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
  .InformationalVersion;

where YOURTYPE is any Type in the Assembly that has the AssemblyInformationalVersion attribute.

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

#2


55  

You can embed a version.txt file into the executable and then read the version.txt out of the executable. To create the version.txt file, use git describe --long

您可以嵌入一个版本。将txt文件放入可执行文件中,然后读取版本。从可执行文件中删除。创建版本。txt文件,使用git description -long

Here are the steps:

下面是步骤:

Use a Build Event to call git

  • Right-click on the project and select Properties

    右键单击项目并选择Properties

  • In Build Events, add Pre-Build event containing (notice the quotes):

    在构建事件中,添加包含(注意引号)的预构建事件:

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

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

    That will create a version.txt file in your project directory.

    这将创建一个版本。项目目录中的txt文件。

Embed the version.txt in the executable

  • Right click on the project and select Add Existing Item
  • 右键单击项目并选择添加现有项目
  • Add the version.txt file (change the file chooser filter to let you see All Files)
  • 添加版本。txt文件(更改文件选择器过滤器,让您查看所有文件)
  • After version.txt is added, right-click on it in the Solution Explorer and select Properties
  • 后的版本。添加txt,在解决方案资源管理器中右键单击并选择Properties
  • Change the Build Action to Embedded Resource
  • 将构建操作更改为嵌入式资源
  • Change Copy to Output Directory to Copy Always
  • 将“复制”更改为“输出”目录以“始终复制”
  • Add version.txt to your .gitignore file
  • 添加版本。txt到你的。gitignore文件

Read the embedded text file version string

Here's some sample code to read the embedded text file version string:

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

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();
        }
    }
}

#3


12  

Another way to do this is to use the NetRevisionTool with some On-Board Visual Studio magic. I will showcase this here for Visual Studio 2013 Professional Edition, but this will work with other versions as well.

另一种方法是使用NetRevisionTool,其中有一些On-Board Visual Studio magic。我将在这里为Visual Studio 2013专业版展示这一点,但这也将与其他版本一起工作。

So first download the NetRevisionTool. You include the NetRevisionTool.exe in your PATH or check it in into your repository and create a visual studio pre-build and a post-build action and change your AssemblyInfo.cs.

首先下载NetRevisionTool。你包括NetRevisionTool。在您的路径中执行exe,或者在您的存储库中检查它,并创建一个visual studio预构建和后构建操作,并更改您的汇编信息。

An example that would add your git-hash to your AssemblyInformationVersion would be the following: In your project settings:

将git-hash添加到程序集informationversion的示例如下:在项目设置中:

enter image description here

in the AssemblyInfo.cs of your project you change/add the line:

在AssemblyInfo。你改变/增加的项目cs:

[assembly: AssemblyInformationalVersion("1.1.{dmin:2015}.{chash:6}{!}-{branch}")]

[组装:AssemblyInformationalVersion(“1.1。{ dmin:2015 },{ chash:6 } { ! } - {分支} "))

in the shown screenshot i checked in NetRevisionTool.exe in the External/bin folder

在截图中我查看了NetRevisionTool。在外部/bin文件夹中的exe

After build, if you then right-click your binary and go to properties then you should see something like the following:

构建之后,如果您右键单击二进制文件并进入properties文件,您应该会看到如下内容:

enter image description here

Hope this helps somebody out there

希望这能帮助别人

#4


10  

I think this question is worth giving a complete step by step answer. The strategy here to is run a powershell script from the pre-build events that takes in a template file and generates an AssemblyInfo.cs file with the git tag + commit count information included.

我认为这个问题值得一步一步的回答。这里的策略是从预构建事件中运行powershell脚本,该脚本接收模板文件并生成汇编信息。使用git标记+提交计数信息的cs文件。

Step 1: make an AssemblyInfo_template.cs file in the Project\Properties folder, based on your original AssemblyInfo.cs but containing:

步骤1:创建一个组装info_template。cs文件在项目\属性文件夹,基于您的原始汇编信息。cs包含:

[assembly: AssemblyVersion("$FILEVERSION$")]
[assembly: AssemblyFileVersion("$FILEVERSION$")]
[assembly: AssemblyInformationalVersion("$INFOVERSION$")]

Step 2: Create a powershell script named InjectGitVersion.ps1 whose source is:

步骤2:创建一个名为InjectGitVersion的powershell脚本。ps1的来源是:

# InjectGitVersion.ps1
#
# Set the version in the projects AssemblyInfo.cs file
#


# Get version info from Git. example 1.2.3-45-g6789abc
$gitVersion = git describe --long --always;

# Parse Git version info into semantic pieces
$gitVersion -match '(.*)-(\d+)-[g](\w+)$';
$gitTag = $Matches[1];
$gitCount = $Matches[2];
$gitSHA1 = $Matches[3];

# Define file variables
$assemblyFile = $args[0] + "\Properties\AssemblyInfo.cs";
$templateFile =  $args[0] + "\Properties\AssemblyInfo_template.cs";

# Read template file, overwrite place holders with git version info
$newAssemblyCOntent= Get-Content $templateFile |
    %{$_ -replace '\$FILEVERSION\$', ($gitTag + "." + $gitCount) } |
    %{$_ -replace '\$INFOVERSION\$', ($gitTag + "." + $gitCount + "-" + $gitSHA1) };

# Write AssemblyInfo.cs file only if there are changes
If (-not (Test-Path $assemblyFile) -or ((Compare-Object (Get-Content $assemblyFile) $newAssemblyContent))) {
    echo "Injecting Git Version Info to AssemblyInfo.cs"
    $newAssemblyContent > $assemblyFile;       
}

Step 3: Save the InjectGitVersion.ps1 file to your solution directory in a BuildScripts folder

步骤3:保存InjectGitVersion。ps1文件到您的解决方案目录中的BuildScripts文件夹

Step 4: Add the following line to the project's Pre-Build events

步骤4:将以下一行添加到项目的预构建事件中

powershell -ExecutionPolicy ByPass -File  $(SolutionDir)\BuildScripts\InjectGitVersion.ps1 $(ProjectDir)

Step 5: Build your project.

步骤5:构建项目。

Step 6: Optionally, add AssemblyInfo.cs to your git ignore file

步骤6:可选地,添加程序集信息。cs到您的git忽略文件

#5


9  

I've created a simple nuget package that you can include in your project which will take care of this for you: https://www.nuget.org/packages/MSBuildGitHash/

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

This nuget package implements a "pure" MSBuild solution. If you'd rather not depend on a nuget package you can simply copy these Targets into your csproj file and it should include the git hash as a custom assembly attribute:

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


  
    
    $(IntermediateOutputPath)gitver
  

  
  

  
  
    
  
  
  
    @(GitVersion)
      



  
  
    $(IntermediateOutputPath)CustomAssemblyInfo.cs
  
  
  
    
  
  
  
    
      <_Parameter1>GitHash
      <_Parameter2>$(BuildHash)
    
  
  
  

There are two targets here. The first one, "GetGitHash", loads the git hash into an MSBuild property named BuildHash, it only does this if BuildHash is not already defined. This allows you to pass it to MSBuild on the command line, if you prefer. You could pass it to MSBuild like so:

这里有两个目标。第一个是“GetGitHash”,它将git散列加载到名为BuildHash的MSBuild属性中,只有在尚未定义BuildHash时才会这样做。这允许您将它传递给命令行上的MSBuild。你可以把它传递给MSBuild:

MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL

MSBuild。exe myproj。csproj / p:BuildHash = MYHASHVAL

The second target, "WriteGitHash", will write the hash value to a file in the temporary "obj" folder named "CustomAssemblyInfo.cs". This file will contain a line that looks like:

第二个目标是“WriteGitHash”,它将把哈希值写入临时“obj”文件夹中的一个文件中,该文件夹名为“CustomAssemblyInfo.cs”。这个文件将包含如下一行:

[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]

[组装:AssemblyMetadata(“GitHash”、“MYHASHVAL”)]

This CustomAssemblyInfo.cs file will be compiled into your assembly, so you can use reflection to look for the AssemblyMetadata at runtime. The following code shows how this can be done when the AssemblyInfo class is included in the same assembly.

这CustomAssemblyInfo。cs文件将被编译到程序集中,因此您可以使用反射在运行时查找程序集元数据。下面的代码演示了如何在将这个程序集包含在同一个程序集中时实现这一点。

using System.Linq;
using System.Reflection;

public static class AssemblyInfo
{
    ///  Gets the git hash value from the assembly
    /// or null if it cannot be found. 
    public static string GetGitHash()
    {
        var asm = typeof(AssemblyInfo).Assembly;
        var attrs = asm.GetCustomAttributes();
        return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
    }
}

Some benefits to this design is that it doesn't touch any files in your project folder, all the mutated files are under the "obj" folder. Your project will also build identically from within Visual Studio or from the command line. It can also be easily customized for your project, and will be source controlled along with your csproj file.

这种设计的一些好处是它不会触及项目文件夹中的任何文件,所有突变的文件都在“obj”文件夹下。您的项目也将在Visual Studio中或命令行中进行相同的构建。它也可以很容易地为您的项目定制,并且将与csproj文件一起由源代码控制。

#6


3  

As the other answer already mentions the git bit, once you have the SHA you can consider generating the AssemblyInfo.cs file of your project in a pre-build hook.

另一个答案已经提到了git位,一旦有了SHA,就可以考虑生成汇编信息了。您项目的cs文件在预构建钩子中。

One way to do this is to create an AssemblyInfo.cs.tmpl template file, with a placeholder for your SHA in say $$GITSHA$$, e.g.

一种方法是创建一个assembly - info .cs。tmpl模板文件,包含您的SHA的占位符,例如$GITSHA$$

[assembly: AssemblyDescription("$$GITSHA$$")]

Your pre build hook then has to replace this placeholder and output the AssemblyInfo.cs file for the C# compiler to pick up.

然后,您的预构建挂钩必须替换这个占位符并输出程序集信息。cs文件,供c#编译器拾取。

To see how this can be done using SubWCRev for SVN see this answer. It shouldn't be hard to do something similar for git.

要了解如何使用SubWCRev来完成SVN,请参见这个答案。为git做类似的事情应该不难。

Other ways would be a "make stage" as mentioned, i.e. write an MSBuild task that does something similar. Yet another way may be to post process the DLL somehow (ildasm+ilasm say), but I think the options mentioned above are probably easiest.

其他的方法是像前面提到的“制造阶段”,例如写一个MSBuild任务,做一些类似的事情。另一种方法可能是以某种方式发布DLL (ildasm+ilasm),但我认为上面提到的选项可能是最简单的。

#7


2  

For a fully automated and flexible method checkout https://github.com/Fody/Stamp. We've successfully used this for our Git projects (as well as the this version for SVN projects)

对于完全自动化和灵活的方法,请检查https://github.com/Fody/Stamp。我们已经成功地将它用于Git项目(以及SVN项目的这个版本)

#8


0  

You can use a powershell one-liner to update all assemblyinfo files with the commit hash.

您可以使用powershell一行程序来使用提交散列更新所有程序集信息文件。

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $cOntent= (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }

#9


0  

I'm using a combination of the accepted answer and a small adition. I have th AutoT4 extension installed (https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4) to re-run the templates before build.

我用的是一个公认答案和一个小建议的组合。我安装了这个AutoT4扩展(https://marketplace.visualstudio.com/items? name = bennormccarthy.autot4),以便在构建之前重新运行模板。

getting version from GIT

I have git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt" in my pre-build event in project properties. Adding git_version.txt and VersionInfo.cs to .gitignore is quite a good idea.

我有git -C $(ProjectDir) describe——long——总是>“$(ProjectDir)git_version。在项目属性的预构建事件中。添加git_version。txt和VersionInfo。从cs到。gitignore是个好主意。

embedding version in metadata

I have added a VersionInfo.tt template to my project:

我添加了一个VersionInfo。tt模板到我的项目:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

<#
if (File.Exists(Host.ResolvePath("git_version.txt")))
{
    Write("[assembly: AssemblyInformationalVersion(\""+ File.ReadAllText(Host.ResolvePath("git_version.txt")).Trim() + "\")]");
}else{
    Write("// version file not found in " + Host.ResolvePath("git_version.txt"));
}

#>

Now I have my git tag + hash in "ProductVersion".

现在我在“ProductVersion”中有了我的git标记+哈希。

#10


0  

Referring to the another answer (https://stackoverflow.com/a/44278482/4537127) i also utilised the VersionInfo.tt text template to generate AssemblyInformationalVersion without AutoT4.

引用另一个答案(https://stackoverflow.com/a/44278482/4537127),我也使用了VersionInfo。tt文本模板生成不需要AutoT4的汇编信息版本。

(Atleast works in my C# WPF application)

(至少适用于我的c# WPF应用程序)

Problem was that the Pre-build events were run after template transformations, so after cloning, the git_version.txt file was not there and build fails. After creating it manually to allow transformation to pass once, it was updated after transformation, and was always one commit behind.

问题是,预构建事件是在模板转换之后运行的,所以在克隆之后,就是git_version。txt文件不存在,构建失败。在手动创建它以允许转换通过一次之后,它在转换后被更新,并且始终是一个提交。

I had to make two adjustments to the .csproj file (this applies at least for Visual Studio Community 2017)

我必须对.csproj文件做两次调整(至少对Visual Studio Community 2017是这样)

1) Import the Text Transformation Targets and make template transformations to run on every build: (Ref https://msdn.microsoft.com/en-us/library/ee847423.aspx)

1)导入文本转换目标,并在每个构建上执行模板转换:(Ref https://msdn.microsoft.com/en-us/library/ee847423.aspx)


    15.0
    $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
    true
    false

and after

在 <进口项目= " $ \ microsoft.csharp(msbuildtoolspath)。目标">


2) Make the git describe run before template transformations (so that git_version.txt is there when VersionInfo.tt is transformed) :

2)让git description在模板转换之前运行(以便使用git_version)。当版本信息时,txt在那里。tt转换):


  

..And the C# code to get the AssemblyInformationalVersion (Ref https://stackoverflow.com/a/7770189/4537127)

. .以及获取汇编信息的c#代码(参见https://stackoverflow.com/a/7770189/4537127)

public string AppGitHash
{
    get
    {
        AssemblyInformationalVersionAttribute attribute = (AssemblyInformationalVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false).FirstOrDefault();

        return attribute.InformationalVersion;
    }
}

..And add the generated files to .gitignore

. .并将生成的文件添加到.gitignore

VersionInfo.cs
git_version.txt

#11


-1  

  1. I hope you know how to call external programs and intercept output at the build-time.
  2. 我希望您知道如何调用外部程序并在构建时截获输出。
  3. I hope you know how to have in git's working directory ignore unversioned files.
  4. 我希望您知道如何在git的工作目录中忽略不可逆文件。

As noted by @learath2, output of git rev-parse HEAD will give you plain hash.

正如@learath2所指出的,git rev-parse HEAD的输出将为您提供一个普通的散列。

If you use tags in Git-repository (and you use tags, isn't it more descriptive and readable than git rev-parse), output may be received from git describe (while also successfully used later in git checkout)

如果您在git存储库中使用标记(并且使用标记,难道它不比git rev-parse更具描述性和可读性吗?

You can call rev-parse|describe in:

你可以调用rev-parse|描述:

  • some make stage
  • 一些制作阶段
  • in post-commit hook
  • 在post-commit钩
  • in smudge filter, if you'll select smudge/clean filters way of implementation
  • 在smudge过滤器中,如果您选择了smudge/clean过滤器的实现方式。

推荐阅读
author-avatar
小唐永远支持小志
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有