trends tendencies repos lib language c# git

c# - repos - github tendencies



Incrustar git commit hash en un dll.Net (12)

  1. Espero que sepas cómo llamar a programas externos e interceptar la salida en el momento de la compilación.
  2. Espero que sepas cómo tener en el directorio de trabajo de git ignorar archivos no versionados.

Como lo señaló @ learath2, la salida de git rev-parse HEAD te dará un hash simple.

Si usa etiquetas en el repositorio Git (y las usa, ¿no es más descriptivo y legible que git rev-parse ), la salida se puede recibir desde git describe (aunque también se usa con éxito más adelante en git checkout )?

Puedes llamar a rev-parse | describe en:

  • algunos hacen escenario
  • en el gancho post-commit
  • en el filtro de manchas, si selecciona la forma de implementación de los filtros de manchas / limpieza

Estoy creando una aplicación C #, usando Git como mi control de versión.

¿Hay una manera de incrustar automáticamente el último hash de confirmación en el ejecutable cuando compilo mi aplicación?

Por ejemplo, imprimir el hash de confirmación en la consola sería algo así como:

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

Tenga en cuenta que esto debe hacerse en tiempo de compilación , no en tiempo de ejecución , ya que mi ejecutable implementado no tendrá acceso al repositorio git.

Una pregunta relacionada para C ++ se puede encontrar here .

EDITAR

Según la solicitud de @ mattanja, estoy publicando el script de git hook que uso en mis proyectos. La puesta en marcha:

  • Los ganchos son scripts de shell de Linux, que se colocan en: path_to_project / .git / hooks
  • Si está utilizando msysgit , la carpeta de msysgit ya contiene algunos scripts de muestra. Para que git los llame, elimine la extensión ''.sample'' del nombre del script.
  • Los nombres de los scripts de enlace coinciden con el evento que los invoca. En mi caso, modifiqué post-commit y post-merge .
  • Mi archivo AssemblyInfo.cs está directamente debajo de la ruta del proyecto (el mismo nivel que la carpeta .git ). Contiene 23 líneas, y uso git para generar el 24.

Como mi linux-shelling está un poco oxidado, la secuencia de comandos simplemente lee las primeras 23 líneas de AssemblyInfo.cs en un archivo temporal, repite el hash de git en la última línea y cambia el nombre del archivo a AssemblyInfo.cs . Estoy seguro de que hay mejores maneras de hacer esto:

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

Espero que esto ayude.


Como la otra respuesta ya menciona el bit git, una vez que tenga el SHA, puede considerar generar el archivo AssemblyInfo.cs de su proyecto en un gancho de precompilación.

Una manera de hacer esto es crear un archivo de plantilla AssemblyInfo.cs.tmpl , con un marcador de posición para su SHA en, por ejemplo, $$ GITSHA $$, por ejemplo

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

Su gancho de compilación previa debe reemplazar este marcador de posición y generar el archivo AssemblyInfo.cs para que el compilador de C # se recupere.

Para ver cómo se puede hacer esto usando SubWCRev para SVN, vea esta respuesta . No debería ser difícil hacer algo similar para git.

Otras formas serían una "etapa de creación" como se mencionó, es decir, escribir una tarea de MSBuild que haga algo similar. Sin embargo, otra manera puede ser publicar el DLL de alguna manera (ildasm + ilasm say), pero creo que las opciones mencionadas anteriormente son probablemente las más fáciles.


Creo que esta pregunta vale la pena dar una respuesta paso a paso completa. La estrategia aquí es ejecutar un script powershell de los eventos de precompilación que toma un archivo de plantilla y genera un archivo AssemblyInfo.cs con la etiqueta git + la información de conteo de confirmación incluida.

Paso 1: cree un archivo AssemblyInfo_template.cs en la carpeta Proyecto / Propiedades, basado en su AssemblyInfo.cs original pero que contenga:

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

Paso 2: crea un script de powershell llamado InjectGitVersion.ps1 cuyo origen es:

# 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; }

Paso 3: Guarde el archivo InjectGitVersion.ps1 en el directorio de su solución en una carpeta BuildScripts

Paso 4: Agregue la siguiente línea a los eventos de precompilación del proyecto

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

Paso 5: Construye tu proyecto.

Paso 6: Opcionalmente, agregue AssemblyInfo.cs a su archivo ignorar git


Estoy usando una combinación de la respuesta aceptada y una pequeña adición. Tengo la extensión AutoT4 instalada ( https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4 ) para volver a ejecutar las plantillas antes de compilar.

obteniendo la versión de GIT

Tengo git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt" en mi evento de construcción previa en las propiedades del proyecto. Agregar git_version.txt y VersionInfo.cs a .gitignore es una buena idea.

incrustar la versión en metadatos

He agregado una plantilla VersionInfo.tt a mi proyecto:

<#@ 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")); } #>

Ahora tengo mi etiqueta git + hash en "ProductVersion".


He creado un paquete nuget simple que puede incluir en su proyecto y que se encargará de esto por usted: https://www.nuget.org/packages/MSBuildGitHash/

Este paquete nuget implementa una solución MSBuild "pura". Si prefiere no depender de un paquete nuget, simplemente puede copiar estos objetivos en su archivo csproj y debería incluir el hash git como un atributo de ensamblaje 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 &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>

Hay dos objetivos aquí. El primero, "GetGitHash", carga el hash git en una propiedad de MSBuild llamada BuildHash, solo hace esto si BuildHash no está ya definido. Esto le permite pasarlo a MSBuild en la línea de comandos, si lo prefiere. Usted podría pasarlo a MSBuild así:

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

El segundo objetivo, "WriteGitHash", escribirá el valor de hash en un archivo en la carpeta temporal "obj" llamada "CustomAssemblyInfo.cs". Este archivo contendrá una línea que se parece a:

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

Este archivo CustomAssemblyInfo.cs se compilará en su ensamblaje, por lo que puede usar la reflexión para buscar los datos de AssemblyMetadata en tiempo de ejecución. El siguiente código muestra cómo se puede hacer esto cuando la clase AssemblyInfo se incluye en el mismo ensamblaje.

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

Algunos de los beneficios de este diseño es que no toca ningún archivo en la carpeta de su proyecto, todos los archivos mutados se encuentran en la carpeta "obj". Su proyecto también se compilará de manera idéntica desde Visual Studio o desde la línea de comandos. También se puede personalizar fácilmente para su proyecto, y será controlado por la fuente junto con su archivo csproj.


Otra forma de hacer esto es usar NetRevisionTool con algo de magia de Visual Studio a bordo. Mostraré esto aquí para Visual Studio 2013 Professional Edition, pero esto también funcionará con otras versiones.

Así que primero descarga el NetRevisionTool. Incluya NetRevisionTool.exe en su RUTA o insértelo en su repositorio y cree una precompilación de Visual Studio y una acción posterior a la compilación y cambie su AssemblyInfo.cs.

Un ejemplo que agregaría su git-hash a su AssemblyInformationVersion sería el siguiente: En la configuración de su proyecto:

en el AssemblyInfo.cs de su proyecto cambia / agrega la línea:

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

en la captura de pantalla mostrada, verifiqué NetRevisionTool.exe en la carpeta Externa / bin

Después de compilar, si hace clic con el botón derecho en su binario y va a propiedades, debería ver algo como lo siguiente:

Espero que esto ayude a alguien por ahí


Otra forma sería generar un archivo Version.cs a partir de un paso de precompilación. Exploré esto en un pequeño proyecto de prueba de concepto que imprime su hash de compromiso actual.

El proyecto se carga en https://github.com/sashoalm/GitCommitHashPrinter .

El código de lote que crea el archivo Version.cs es este:

@echo off echo "Writing Version.cs file..." @rem Pushd/popd are used to temporarily cd to where the BAT file is. pushd $(ProjectDir) @rem Verify that the command succeeds (i.e. Git is installed and we are in the repo). git rev-parse HEAD || exit 1 @rem Syntax for storing a command''s output into a variable (see https://.com/a/2340018/492336). @rem ''git rev-parse HEAD'' returns the commit hash. for /f %%i in (''git rev-parse HEAD'') do set commitHash=%%i @rem Syntax for printing multiline text to a file (see https://.com/a/23530712/492336). ( echo namespace GitCommitHashPrinter echo { echo class Version echo { echo public static string CommitHash { get; set; } = "%commitHash%"; echo } echo } )>"Version.cs" popd



Puede incrustar un archivo version.txt en el archivo ejecutable y luego leer el archivo version.txt fuera del archivo ejecutable. Para crear el archivo version.txt , use git describe --long

Aquí están los pasos:

Usa un evento de construcción para llamar a git

  • Haga clic derecho en el proyecto y seleccione Propiedades

  • En Eventos de compilación, agregue un evento precompilación que contenga (observe las citas):

    "C: / Archivos de programa / Git / bin / git.exe" describe --long> "$ (ProjectDir) / version.txt"

    Eso creará un archivo version.txt en el directorio de su proyecto.

Incruste la version.txt en el ejecutable

  • Haga clic derecho en el proyecto y seleccione Agregar elemento existente
  • Agregue el archivo version.txt (cambie el filtro de selección de archivos para que pueda ver Todos los archivos)
  • Después de agregar version.txt , haga clic derecho en él en el Explorador de soluciones y seleccione Propiedades
  • Cambiar la acción de compilación a recurso incrustado
  • Cambiar Copia a Directorio de Salida para Copiar Siempre
  • Agregue version.txt a su archivo .gitignore

Lea la cadena de versión del archivo de texto incrustado

Aquí hay algunos ejemplos de código para leer la cadena de versión del archivo de texto incrustado:

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


Puede utilizar una línea de PowerShell para actualizar todos los archivos de información de ensamblaje con el hash de confirmación.

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


Refiriéndome a la otra respuesta ( https://.com/a/44278482/4537127 ) también VersionInfo.tt plantilla de texto VersionInfo.tt para generar AssemblyInformationalVersion sin AutoT4.

(Atleast funciona en mi aplicación C # WPF)

El problema fue que los eventos de Pre-compilación se ejecutaron después de las transformaciones de la plantilla, así que después de la clonación, el archivo git_version.txt no estaba allí y la compilación falla. Después de crearlo manualmente para permitir que la transformación pase una vez, se actualizó después de la transformación y siempre hubo un compromiso detrás .

Tuve que hacer dos ajustes en el archivo .csproj (esto se aplica al menos para Visual Studio Community 2017)

1) Importe los Objetivos de transformación de texto y haga transformaciones de plantilla para ejecutar en cada compilación: (Ref https://msdn.microsoft.com/en-us/library/ee847423.aspx )

<PropertyGroup> <VisualStudioVersion Condition="''$(VisualStudioVersion)'' == ''''">15.0</VisualStudioVersion> <VSToolsPath Condition="''$(VSToolsPath)'' == ''''">$(MSBuildExtensionsPath32)/Microsoft/VisualStudio/v$(VisualStudioVersion)</VSToolsPath> <TransformOnBuild>true</TransformOnBuild> <TransformOutOfDateOnly>false</TransformOutOfDateOnly> </PropertyGroup>

y después de <Import Project="$(MSBuildToolsPath)/Microsoft.CSharp.targets" />

<Import Project="$(VSToolsPath)/TextTemplating/Microsoft.TextTemplating.targets" />

2) Haga que git describe ejecute antes de las transformaciones de la plantilla (de modo que git_version.txt esté allí cuando se transforme VersionInfo.tt ):

<Target Name="PreBuild" BeforeTargets="ExecuteTransformations"> <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(ProjectDir)git_version.txt" /> </Target>

..Y el código C # para obtener la AssemblyInformationalVersion (Ref https://.com/a/7770189/4537127 )

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

..Y agrega los archivos generados a .gitignore

VersionInfo.cs git_version.txt


Usamos etiquetas en git para rastrear versiones.

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

Puedes obtener la versión con hash desde git a través de:

git describe --long

Nuestro proceso de compilación pone el hash git en el atributo AssemblyInformationalVersion del archivo AssemblyInfo.cs:

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

Una vez que compile, puede ver la versión desde Windows Explorer:

También puedes obtenerlo programáticamente a través de:

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

donde YOURTYPE es cualquier tipo en el ensamblado que tiene el atributo AssemblyInformationalVersion.