I recently asked about keyword expansion in Git and I'm willing to accept the design not to really support this idea in Git.
For better or worse, the project I'm working on at the moment requires SVN keyword expansion like this:
svn propset svn:keywords "Id" expl3.dtx
to keep this string up-to-date:
$Id: expl3.dtx 803 2008-09-11 14:01:58Z will $
But I would quite like to use Git to do my version control. Unfortunately, git-svn doesn't support this, according to the docs:
"We ignore all SVN properties except svn:executable"
But it doesn't seem too tricky to have this keyword stuff emulated by a couple of pre/post commit hooks. Am I the first person to want this? Does anyone have some code to do this?
Here is a sample project containing the configuration and filter code needed for adding RCS keyword support to a git project:
https://github.com/turon/git-rcs-keywords
It's not as simple to setup as one would like, but it seems to work. It uses a smudge/clean filter pair written in perl (similar to what emk's answer described), and yes, it will touch all files with the extensions set in .gitattributes, generally slowing things down a bit.
That is not true. $Date$ etc. expand to the value which holds at checkin time. That is much more useful anyway. So it doesn't change on other revisions or branches, unless the file is actually re-checked-in. From the RCS manual:
This also means that the suggested answer above, with the rcs-keyword.smudge filter, is incorrect. It inserts the time/date of the checkout, or whatever it is that causes it to run.
What's going on here: Git is optimized to switch between branches as quickly as possible. In particular,
git checkout
is designed to not touch any files that are identical in both branches.Unfortunately, RCS keyword substitution breaks this. For example, using
$Date$
would requiregit checkout
to touch every file in the tree when switching branches. For a repository the size of the Linux kernel, this would bring everything to a screeching halt.In general, your best bet is to tag at least one version:
...and then call the following command from your Makefile:
Here, git is telling me that I'm working on an anonymous version 6 commits past v0.5.15.1, with an SHA1 hash beginning with
g61cde1d
. If you stick the output of this command into a*.h
file somewhere, you're in business, and will have no problem linking the released software back to the source code. This is the preferred way of doing things.If you can't possibly avoid using RCS keywords, you may want to start with this explanation by Lars Hjemli. Basically,
$Id$
is pretty easy, and you if you're usinggit archive
, you can also use$Format$
.But, if you absolutely cannot avoid RCS keywords, the following should get you started:
On my system, I get:
If you have trouble getting the shell escapes in the
smudge
andclean
commands to work, just write your own Perl scripts for expanding and removing RCS keywords, respectively, and use those scripts as your filter.Note that you really don't want to do this for more files than absolutely necessary, or git will lose most of its speed.
You could set the ident attribute on your files, but that would produce strings like
where
deadbeef...
is the sha1 of the blob corresponding to that file. If you really need that keyword expansion, and you need it in the git repo (as opposed to an exported archive), I think you're going to have to go with theident
gitattribute with a custom script that does the expansion for you. The problem with just using a hook is then the file in the working tree wouldn't match the index, and git would think it's been modified.