We have lots of NuGet. Every time we build, we publish a new version. but every build does not change the source code of the code in that version. wouldn't it be nice if we could detect that the subdirectory hasn't changed and so has the same version it did last time we built it?

We use gitversion, so we already have a way to get the version for the current commit. Maybe we can use that to get the version for a subdirectories latest commit? Sure we can!

To get the version for the latest commit, we need the latest commit. Turns out you can use

$pathToFolder = "C:\dev\MyProject\MySubfolder"
$commitHash = git log -n 1 --format="%H" -- $pathToFolder

Here we run a git log command to get the full commit hash, which we can save into a variable $commitHash. Now we have something to give to gitversion.

There is a command in gitversion, \c, which takes a commit hash and runs for that instead of for the current commit. All we need to do is the following:

$folderVersion = gitversion /c $commitHash | ConvertFrom-Json

and new we have an object in $folderVersion that we can inspect and get out all the version information, from $folderVersion.SemVer, $folderVersion.NuGetVersionV2, and even $folderVersion.FullBuildMetaData!

What you do from here to integrate with the rest of your build scripts is up to you. One I have used is to go through that folder and replace version information, such as in *.nuspec files. Note here my *.nuspec file has a placeholder $version$ as the version number already in place.

$NewVersion = "" ## Version from some source, like gitversion
$Sha = "" ## You can include the sha the version is from into the nuspec file
$FileFullPath = "" ## filepath from some sort of search for *.nuspec files
$TmpFile = $FileFullPath + ".tmp"

[ xml ] $fileContents = Get-Content -Path $o.FullName

if ($fileContents.package.metadata.version -eq $null) {
  $child = $fileContents.CreateElement("version", $fileContents.DocumentElement.NamespaceURI)
  $fileContents.package.metadata.AppendChild($child)
  $fileContents.package.metadata.version = "$version$"
}
  
$NewDescription = $fileContents.package.metadata.description + ' (' + $Sha + ')';
$fileContents.package.metadata.description = $NewDescription

if($Version) {
  $fileContents.package.metadata.version = $NewVersion
}

$fileContents.Save($TmpFile)    
     
move-item $TmpFile $FileFullPath -force

Another useful use-case is to execute GitVersion with /updateassemblyinfo .\Properties\AssemblyInfo.cs as an argument, to target and update a specific project's assembly info version as well.