Question

I have a few Rails applications and I use Git as the version control system. I use either GitHub or Beanstalk as the repository hosts.

What I am trying to is quite simple in theory. Somehow show the latest commit ID number (hash?) in the footer of the web application. So that when I am looking at the web application I can check that it's committed and deployed correctly.

I can imagine there are two methods to tackle this. The first would be a possible feature of Git that allows the output of the commit ID. The second would be a post-commit web hook (both Beanstalk and GitHub allow this).

Has anyone ever found a way to do this, or something similar?

Thanks,

Danny

Was it helpful?

Solution

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.

OTHER TIPS

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top