I come from RCS, where revision numbers are easy to insert into files with RCS keyword strings such as $Revision: $, $Id: $ and $Header: $.
There are various posts around of different ways of using revision numbers in Git, e.g. http://stackoverflow.com/questions/4120001/what-is-the-git-equivalent-for-revision-number
When using tags to record release revision numbers, we can use git describe to obtain reasonable-looking revision numbers, e.g. 1.2.1-2-g17880f1, where 1.2.1 is the most recent tag on the current branch, 2 is the number of commits made since the tag, and 17880f1 is the (short) SHA of the current commit (prefixed with g for "git"). These numbers have the benefit of monotonically increasing in the -<number-of-commits>- part, and presumably you would use some sort of meaningful release revision numbers in tags, so they should be fairly easy to understandy by non-technical people (ignoring the -g<SHA> at the end).
Ideally there would be a way to insert revision numbers, e.g. on installation with make install or the equivalent, to emulate RCS's co behaviour. Ideally it should use standardized tools to do this.
Sometimes I want the version number in a variable, e.g. in Perl
#!/usr/bin/perl
my $VERSION = '1.2.1';We could instead insert a dummy value that is used as a template, say
#!/usr/bin/perl
my $VERSION = '1.1';and use a patch like the following (cut-down) unified diff to insert a revision number:
@@ -0 +0 @@
-my $VERSION = '1.1';
+my $VERSION = '1.2.1-2-g17880f1';This is easy to produce in a shell to incorporate the current git describe revision number, and can be piped directly into patch:
#!/bin/bash
(
echo "@@ -0 +0 @@"
echo "-my \$VERSION = '1.1';"
echo "+my \$VERSION = '$(git describe)';"
) | patch --silent --unified --reject-file=- --output=OUTPUTFILE INPUTFILENote the line numbers in the unified diff are both 0. Because patch scans for a matching context, and we have only supplied a single line of context, patch will replace (the first occurrence of) this text anywhere in the file.
Something other than patch is required if we want to replace keywords in a number of places within a file, e.g. with arbitrary RCS-like $Revision: $ strings throughout. One idea is to use sed, e.g.
#!/bin/bash
sed "s/\\\$Revision\\(:[^\$]*\\)\?\\$/\$Id: $(git describe) \$/g" INPUTFILE > OUTPUTFILEHowever, the escaping of shell meta-characters in the double-quoted string, along with escaping sed meta-characters, is very ugly and error-prone. If this were incorporated into a Makefile recipe, it would be even uglier with all the $s needing to be escaped by doubling them:
# Makefile
OUTPUTFILE: INPUTFILE
sed "s/\\\$$Revision\\(:[^\$$]*\\)\?\\$$/\$$Id: $$(git describe) \$$/g" INPUTFILE > OUTPUTFILEUgly, eh?
| RCS keyword | Git equivalent or similar | notes |
|---|---|---|
| git describe | ||
| git log -n1 --pretty=%ai | or %aD or %ad | |
| git log -n1 --pretty=%ae | sed 's/@.*$//' | leave out the sed part if you don't mind the full email address | |
| git diff --exit-code || git diff --cached --exit-code || id -nu | assume the current user is the locker |
http://stackoverflow.com/a/1796675