【问题标题】:How can I get the Git commit hash in my PS script?如何在我的 PS 脚本中获取 Git 提交哈希?
【发布时间】:2017-05-14 10:30:00
【问题描述】:

我正在使用 PowerShell 脚本调用 msbuild 并将版本号传递给 OctopusDeploy,如下所示:

msbuild "Xyz.sln" /t:Rebuild /p:Configuration=Release /p:RunOctoPack=true /p:OctopackPackageVersion=$versionNumber

... 其中 $versionNumber 在 PS 脚本中生成。我想要做的是将 Git 提交哈希的前 16 个字符添加到版本字符串的末尾,所以它最终看起来像:

2.yyyyMMdd.HHmmss-git-6d34e44340f95c2a

我该怎么做?我可以让msbuild 或 Visual Studio 以某种方式返回当前的 git 提交哈希,考虑到它们现在有内置的 Git 支持吗?

【问题讨论】:

  • 如果您想使用 git 和 .Net 管理版本控制,请随时查看 GitVersion github.com/GitTools/GitVersion,它可以帮助您进行语义版本控制(好习惯!)。甚至还有一个 msbuild 任务......时间戳不是一个很好的做法,您应该更喜欢 git 拓扑(gitversion 可以帮助您轻松实现)

标签: git powershell msbuild


【解决方案1】:

您实际上可以直接在 msbuild 中执行此操作,这样它就可以在 VS 和大多数 CI 系统中运行而无需任何额外步骤(例如 PowerShell 脚本),即使在跨平台 dotnet CLI 和单声道上也是如此。

您可以在项目或解决方案(> 影响所有项目)目录中创建一个名为 Directory.Build.targets 的文件,其内容如下(假设 MSBuild 15 / VS 2017。如果较低,则需要手动导入或将此目标插入到每个项目)

<Project>
  <Target Name="DetermineOctopackVersion" BeforeTargets="Build" Condition=" '$(RunOctoPack)' == 'true' ">
    <Exec Command="git rev-parse HEAD" ConsoleToMSBuild="true" StandardOutputImportance="low">
      <Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHash" />
    </Exec>
    <PropertyGroup>
      <VersionDatePart>$([System.DateTime]::get_Now().ToString(yyyyMMdd.HHmmss))</VersionDatePart>
      <OctopackPackageVersion>2.$(VersionDatePart)-git-$(GitCommitHash.Substring(0,16))</OctopackPackageVersion>
    </PropertyGroup>
  </Target>
</Project>

如果您希望在每次构建时都设置该属性,而不仅仅是当 RunOctoPack 是 true 时,只需删除 Condition 属性即可。

但如果需要在 PowerShell 中进行,可以调用 git 命令并捕获其输出:

$commitHash = (git rev-parse HEAD).Substring(0,16)
$versionDatePart = [System.DateTime]::Now.ToString('yyyyMMdd.HHmmss')
$version = "1.$versionDatePart-git-$commitHash"

如果你真的想避免调用git(尽管没有安装 git 就没有完整的构建系统设置..)你也可以在 PS 或 MSBuild 中使用[System.IO.File]::ReadAllText(".git\refs\heads\master") 从 git 目录中读取(在分离状态,.git\HEAD 将包含哈希,当使用分支时,它将包含文件的位置以查找哈希)。

【讨论】:

  • 我认为您的两个解决方案都需要在机器上安装git.exe 是否正确?在这种情况下,我无法做出这样的假设。
  • 最佳实践是使用用于设置构建的 git 版本。您可以像在其他版本中一样加载 libgit# 或自己查找文件,但我强烈建议使用 git.exe方法是它是最跨平台的(我个人认为没有安装 git 的环境不是开发或构建环境)
  • 例如如果您使用dotnet msbuild,则无法下载和解析保证在主机运行时中工作的 LibGit# 版本(因为不需要安装 VS,您可以在 linux 上运行)
  • 用于“设置构建”的 git 版本是什么意思?
【解决方案2】:

由于您想避免按照 here 调用 git.exe 并且您希望在 PowerShell 中进行提交处理,您可以像这样将 C# 解决方案转换为 PowerShell。

[System.Reflection.Assembly]::LoadFrom("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\LibGit2Sharp.dll") | Out-Null

$repo = [LibGit2Sharp.Repository]::new("C:\MyRepo")
$repo.Commits | Select-Object -First 1

这将返回带有类似数据的 LibGit2Sharp 提交对象

Message      : Further harden mutex closing process

MessageShort : Further harden mutex closing process
Encoding     : UTF-8
Author       : 
Committer    : 
Tree         : {.gitattributes, .gitignore, Build, Doc...}
Parents      : {fe26fc1a476f18bfa8a70c315fdbd96f1434d29c}
Notes        : {}
Id           : 1ba7bce90444a323fa9079cb06e5921afd0c3cd8
Sha          : 1ba7bce90444a323fa9079cb06e5921afd0c3cd8
Repository   : LibGit2Sharp.Repository

您需要使用 32 位 (x86) PowerShell.exe 调用它。

【讨论】:

  • 为什么需要 32 位版本,没有的话有什么办法吗?
  • 请注意,对于 VS 2017,每次安装的可能会有所不同,具体取决于 VS 的版本(社区、企业、.. 和发布/预览版),所有这些都可以并排安装-边
【解决方案3】:

我最后所做的只是将 NGit 捆绑到我的 Powershell 脚本(文件 NGit.dll、Sharpen.dll 和 ICSharpCode.SharpZipLib.dll)旁边,然后使用类似这样的代码生成带有 git hash 后缀的版本号:

[System.Reflection.Assembly]::LoadFrom("Ngit.dll") | Out-Null
[System.Reflection.Assembly]::LoadFrom("Sharpen.dll") | Out-Null
[System.Reflection.Assembly]::LoadFrom("ICSharpCode.SharpZipLib.dll") | Out-Null

# *** Git repo base path (should contain .sln file) ***
$repoPath = "C:\Path\To\Repo"

# *** OctopusDeploy API key for publishing ***
$octoApiKey = "API-[PublishKey]"

#######################################################

# *** Get and process current Git commit hash ***
$sharpenRepoPath = New-Object -TypeName Sharpen.FilePath -ArgumentList "$($repoPath)\.git"
$repoBuilder = New-Object -TypeName NGit.RepositoryBuilder
$repo = $repoBuilder.SetGitDir($sharpenRepoPath).Build()
$headHash = $repo.Resolve("HEAD").Name.Substring(0,12)

# *** Version when pushing to OctopusDeploy NuGet ***
$versionNumber = "2." + [datetime]::now.tostring("yyyyMMdd.HHmmss") + "-git-" + $headHash

# *** Pause before publish ****
Write-Host "About to publish to OctopusDeploy NuGet with version number:"
Write-Host "    $($versionNumber)"
cmd /c pause

# *** OctopusDeploy build and push ***
msbuild "$repoPath\MySolution.sln" /t:Rebuild /p:Configuration=Release /p:RunOctoPack=true /p:OctopackPackageVersion=$versionNumber /p:OctoPackPublishPackageToHttp=https://my.nuget.server/nuget/packages /p:OctoPackPublishApiKey=$octoApiKey

【讨论】:

    猜你喜欢
    • 2014-10-29
    • 2021-06-13
    • 2023-03-16
    • 1970-01-01
    • 2013-02-06
    • 2012-12-31
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    相关资源
    最近更新 更多