首先澄清一下:post-commit钩子不能在in一次提交中添加commit-id,因为commit id依赖于top tree(代表top directory)的commit,top tree的id反过来取决于其成员的 id,而文件的 id 取决于其内容……而该内容将包括提交 id。不可能。
但是让我们来看看不同的解决方案:
实时、服务器端脚本
如果您的网络应用程序是从非裸 git 存储库实时部署的(我希望您知道自己在做什么。推入非裸存储库,即带有结帐/工作树的存储库),那么您的网络应用程序可以检查 HEAD通过使用 git rev-parse HEAD(提供提交的 SHA-1)或更好的 git describe --dirty(--dirty 选项将使返回的字符串包含您是否有未提交的更改的信息在工作区),或git describe --always HEAD。
git rev-parse HEAD 给出类似7611062b4ba6d1ebc4cf3e63c11204a4f5057660 的内容,而git describe --dirty 给出类似v1.7.3.2-95-g7611062 的内容(这意味着提交带有7611062 的缩写SHA-1,提交标记为'v1.7.3.2' 后有95 次提交) ,但这取决于您使用带注释的标签来标记发布。
这种情况的一个变体是让 Web 应用程序从存储库中检查 HEAD,该存储库位于同一文件系统的其他位置,例如git --git-dir=/path/to/.git describe HEAD。
旁注:如果你使用 Ruby,你可能想要使用 grit 库。 git rev-parse HEAD 版本的等价物可能是(未经测试!):
require 'grit'
include Grit
repo = Repo.new("/var/git/app.git")
head = repo.commits('HEAD', 1)
app_version = head.id
由 git checkout 提供的实时静态文件
编辑: 添加部分 2010-10-23 13:33 +0000
如果您从非裸 git 存储库的签出(工作树)提供文件(不是您的情况),您可以使用 filtergitattribute 的 'smudge' 和 'clean' 命令执行 CVS - 类似于结帐/签入时的关键字扩展。
在.gitattributes 文件中,您将定义filter 属性应该作用于的文件:
*.rb 过滤器=commitid
您在 git 配置文件中定义过滤器(例如在.git/config 中),例如
[过滤“提交”]
smudge = sed -e "s/\$Revision: ?\$/\$Revision: $(git rev-parse HEAD)\$/1"
clean = sed -e "s/\$Revision: ?[^$]*\$/\$Revision: \$/1"
smudge 过滤器会将 '$Revision: $' 替换为例如'$Revision: v1.7.3.2-95-g7611062' 在结帐时(这意味着签出的文件将包含这个类似 CVS 的关键字扩展)。 clean 过滤器将在将文件内容存储在 git 对象数据库(在 git 存储库中)时删除扩展;否则你会在比较文件等时遇到问题。
使用git archive 部署
如果您改为部署您的网络应用程序,因此它不会驻留在实时存储库中(它有其怪癖 wrt. 推入它,并且可能存在安全缺陷),并且您在某处使用 git archive(例如压缩应用程序将其上传到您的托管站点),您可以使用关键字替换。
首先你需要告诉 Git 你想用git archive 替换文件中的关键字。您可以通过为给定文件设置export-subst 来做到这一点,例如通过添加到.gitattributes 文件
*.rb 出口替代品
然后添加到包含/生成页面页脚的文件中,例如
$格式:%H$
它将被提交哈希替换(参见漂亮格式描述,例如在git-log 手册页中)。
已部署,使用一些部署脚本
如果您使用某种脚本/脚本机制来部署您的网络应用程序,您应该遵循Jefromi advice 让您的部署脚本嵌入版本信息。
您将不得不询问其他人如何设置Capistrano(假设您将其用于部署)以发布:部署将您的“app.rb”文件中的“@@VERSION@@”占位符替换为@的结果987654352@... Git 项目 Makefile uses sed for that.