Show the latest commit value within a web application?

百般思念 提交于 2019-12-03 12:28:51
Jakub Narębski

First, a clarification: post-commit hook cannot add commit-id to file in a commit, because commit id depends on commit of the top tree (representing top directory), id of top tree in turn depends on ids of its members, and id of a file depends on its contents... and this content is to include commit id. Not possible.

But let's take a look at different solutions:

Live, server side scripting

If your web app is deployed live from non-bare git repository (I hope you know what you are doing wrt. pushing into non-bare repository, i.e. repository with checkout / working tree), then your web app can check HEAD by using git rev-parse HEAD (gives SHA-1 of commit), or better git describe --dirty (the --dirty option would make returned string contain information whether you have uncomitted changes in working area), or git describe --always HEAD.

git rev-parse HEAD gives something like 7611062b4ba6d1ebc4cf3e63c11204a4f5057660, while git describe --dirty gives something like v1.7.3.2-95-g7611062 (which means commit with abbreviated SHA-1 of 7611062, 95 commits after commit tagged 'v1.7.3.2'), but it depends on you tagging releases using annotated tags.

A variant of this would be to have web app to check HEAD from repository which is somewhere else on the same filesystem, e.g. with git --git-dir=/path/to/.git describe HEAD.

Sidenote: if you use Ruby, you probably want to use grit library. The equivalent of git rev-parse HEAD version would probably be (untested!):

require 'grit'
include Grit

repo = Repo.new("/var/git/app.git")
head = repo.commits('HEAD', 1)

app_version = head.id


Live, static files served from git checkout

Edit: section added 2010-10-23 13:33 +0000
If you serve your files from checkout (worktree) of non-bare git repository (not your situation), you can use 'smudge' and 'clean' commands of filter gitattribute to perform CVS-like keyword expansion on checkout / checkin.

In .gitattributes file you would define files on which filter attribute should act:

*.rb filter=commitid

You define filter in git config file (e.g. in .git/config), for example

[filter "commitid"]
        smudge = sed -e "s/\$Revision: ?\$/\$Revision: $(git rev-parse HEAD)\$/1"
        clean =  sed -e "s/\$Revision: ?[^$]*\$/\$Revision: \$/1"

The smudge filter would replace '$Revision: $' with e.g. '$Revision: v1.7.3.2-95-g7611062' on checkout (this means that checked outfiles would contain this CVS-like keyword expanded). The clean filter would remove expansion when storing file contents in git object database (in git repository); otherwise you would have problems with comparing file etc.


Deployed with use of git archive

If you instead deploy your web app, so it doesn't reside in live repository (which has its quirks wrt. pushing into it, and which has possible security drawbacks), and you use git archive somewhere (e.g. to zip app to upload it to your hosting site), you can make use of keyword substitution.

First you need to tell Git that you want keywords in a file replaced by git archive. You do that by setting export-subst for given file, for example by adding to .gitattributes file

*.rb export-subst

and then adding to your file that contains/generates page footer e.g

$Format:%H$

which will be replaced by commit hash (see pretty-formats description e.g. in git-log manpage).


Deployed, using some deployment script

If you use some kind of script / scripted mechanism to deploy your web app, you should follow Jefromi advice of having your deploy script embed version information.

You would have to ask somebody else how to set Capistrano (assuming that you use it for deployment) to post:deployment replace '@@VERSION@@' placeholder in your 'app.rb' file with result of git describe --always HEAD... Git project Makefile uses sed for that.

I believe what you'll end up wanting to do is, as a part of your "build" process (deployment, your case?), store the output of git rev-parse HEAD or git describe HEAD (better, assuming you tag releases) in a file. Your app can then display the contents of the file. The commit hash can't ever actually be part of any tracked content (the hash of the commit depends on the tracked content). Of course, if your app is running out of a repo, you could simply run the command from the app, but it's a lot more elegant to just do it once.

This is the approach taken by git itself, by the way. It has a teeny shell script which basically dumps git describe output to GIT-VERSION-FILE, which is then compiled in to provide the version information.

Hopefully I haven't misunderstood your situation - I'm a little confused by you saying "a possible feature of Git that allows the output of the commit ID". This is a very basic capability of git.

First, the answer to your question, run the following command in your ruby script:

`git log -n1 | head -1`.split.last

Second: What do you mean you use beanstalk as your repository host? Isn't beanstalk a queueing server?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!