I'm building a C# application, using Git as my version control.
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.
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:
- The hooks are linux shell scripts, which are placed under: path_to_project\.git\hooks
- 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.
- 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.
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:
#!/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.
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.
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.
An example that would add your git-hash to your AssemblyInformationVersion would be the following: In your project settings:
in the AssemblyInfo.cs of your project you change/add the line:
[assembly: AssemblyInformationalVersion("1.1.{dmin:2015}.{chash:6}{!}-{branch}")]
in the shown screenshot i checked in NetRevisionTool.exe in the External/bin folder
After build, if you then right-click your binary and go to properties then you should see something like the following:
Hope this helps somebody out there
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.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.Your pre build hook then has to replace this placeholder and output the AssemblyInfo.cs file for the C# compiler to pick up.
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.
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.
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.
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.embedding version in metadata
I have added a
VersionInfo.tt
template to my project:Now I have my git tag + hash in "ProductVersion".
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
Here are the steps:
Use a Build Event to call git
Right-click on the project and select Properties
In Build Events, add Pre-Build event containing (notice the quotes):
"C:\Program Files\Git\bin\git.exe" describe --long > "$(ProjectDir)\version.txt"
That will create a version.txt file in your project directory.
Embed the version.txt in the executable
Read the embedded text file version string
Here's some sample code to read the embedded text file version string:
Referring to the another answer (https://stackoverflow.com/a/44278482/4537127) i also utilised the
VersionInfo.tt
text template to generateAssemblyInformationalVersion
without AutoT4.(Atleast works in my C# WPF application)
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.I had to make two adjustments to the .csproj file (this applies at least for 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)
and after
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
2) Make the
git describe
run before template transformations (so thatgit_version.txt
is there whenVersionInfo.tt
is transformed) :..And the C# code to get the
AssemblyInformationalVersion
(Ref https://stackoverflow.com/a/7770189/4537127)..And add the generated files to .gitignore
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.
Step 1: make an AssemblyInfo_template.cs file in the Project\Properties folder, based on your original AssemblyInfo.cs but containing:
Step 2: Create a powershell script named InjectGitVersion.ps1 whose source is:
Step 3: Save the InjectGitVersion.ps1 file to your solution directory in a BuildScripts folder
Step 4: Add the following line to the project's Pre-Build events
Step 5: Build your project.
Step 6: Optionally, add AssemblyInfo.cs to your git ignore file